Инициализация в типах аннотаций и статическом блоке
Я пытался сделать некоторую логику при загрузке класса типа аннотации. Естественно, статический блок пришел мне в голову.
Но, к сожалению, это не разрешено, ошибка компиляции в Eclipse:
Syntax error, insert "enum Identifier" to complete EnumHeader
Моя аннотационная декларация:
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@Documented
@Retention(RUNTIME)
@Target(FIELD)
@Validate
public @interface StringSize {
int max();
int min() default 0;
static {
Validator.registerCallback(StringSize.class, (Field f, Object parent) -> {
Object o = f.get(parent);
if(!(o instanceof CharSequence))
throw new IllegalAnnotationException("@StringSize allowed on CharSequence fields only.");
CharSequence str = (CharSequence) o;
StringSize size = f.getAnnotation(StringSize.class);
if(str.length() < size.min())
throw new AssertionError(str + " - length < " + size.min());
if(str.length() > size.max())
throw new AssertionError(str + " - length > " + size.max());
});
}
}
Я пытаюсь создать валидатор, который проходит через поле за полем и проверяет наличие любых недопустимых значений.
Теперь эта структура полностью не знает о том, что считается "недопустимым значением", то есть любой потенциальный пользователь этой структуры может создавать свои собственные правила, создавая любое количество пользовательских аннотаций и сопоставляя его с методом обратного вызова, который знает, как чтобы подтвердить это.
@Validate
пользовательская метааннотация, используемая в платформе валидации для пометки аннотации как валидатора (аналогично CDI @Qualifier
). Все, что делает каркас, это когда Validator.validate(obj)
вызывается для сканирования всех полей, если какая-либо из ее аннотаций имеет метааннотацию @Validate
найдите соответствующий метод обратного вызова и вызовите его с этим полем, переданным в качестве аргумента. Обратный вызов вызывает исключение для любого найденного недопустимого значения.
Я пытаюсь найти общий способ сделать отображение аннотации-обратного вызова, поэтому конечный пользователь не должен был бы делать это вручную, а должен был автор пользовательской аннотации. Так что это то, что я пытался сделать.
Есть идеи, как преодолеть это ограничение?
1 ответ
Это на самом деле не решает проблему, но является хорошей альтернативой.
Как видно из моего поста, я определил метааннотацию @Validate
как маркер для моей структуры проверки. У меня также есть интерфейс (который на самом деле использует лямбда-выражение) ValidateCallback
,
С этим на месте, я просто должен добавить value()
в @Validate
:
public @interface Validate {
Class<? extends ValidateCallback> value();
}
Теперь я могу отказаться от системы регистрации, которую я использовал ранее. Все, что мне нужно сделать, это просто вызвать связанный функциональный интерфейс.