2014-11-06 4 views
0

Рассмотрим следующий пример, я создаю пользовательские боба проверки ограничений с помощью нового типа аннотаций:Пользовательские проверки боб абстрактным классом или интерфейсом

@Target({ METHOD, FIELD, ANNOTATION_TYPE }) 
@Retention(RUNTIME) 
@Constraint(validatedBy = MyAbstractOrInterfaceValidator.class) 
@Documented 
public @interface MyAnnotation { 

    String message() default "{}"; 

    Class<?>[] groups() default {}; 

    Class<? extends Payload>[] payload() default {}; 

    SomeClass value(); 

} 

Мой вопрос: может быть MyBastractOrInterfaceValidator класс абстрактный класс или интерфейс? Как я могу контролировать, какая реализация этого интерфейса или абстрактного класса используется для проверки элемента, на который помещена аннотация?

+0

Из интереса, какой был бы ваш прецедент для этого? – Gunnar

+0

Упаковка. Мне нужно проверять классы сущностей, которые находятся в отдельном проекте, который не должен зависеть от проекта impl, где мне бы хотелось, чтобы классы валидатора были. –

+0

Ах, всегда хорошо знать мотивацию :) Написал ответ на это. – Gunnar

ответ

0

См http://docs.oracle.com/javaee/7/api/javax/validation/Constraint.html

Во-первых, обратите внимание, что validatedBy является Class<? extends ConstraintValidator<?,?>>[], что это массив, а не один класс.

Во-вторых, нет смысла использовать интерфейс или абстрактный класс, потому что этот класс необходимо создать.

Но, если вы хотите изменить реализацию валидатора в среде выполнения, попробуйте использовать это:

public class MyValidator implements ConstraintValidator<MyAnnotation, String> { 
    //store the Class information in a static variable 
    private static Class<? extends ConstraintValidator<MyAnnotation, String>> implementationClass = MyValidatorOne.class; 

    //and change it by an accessor 
    public static void setImplementationClass(Class<? extends ConstraintValidator<MyAnnotation, String>> implClass) { 
     this.implementationClass = implClass; 
    } 

    //this delegate will do all the job 
    private final ConstraintValidator<MyAnnotation, String> implementation; 
    public MyValidator() { 
     implementation = implementationClass.newInstance(); 
    } 

    @Override 
    void initialize(MyAnnotation constraintAnnotation) { 
     implementation.initialize(constraintAnnotation); 
    } 

    @Override 
    boolean isValid(T value, ConstraintValidatorContext context) { 
     return implementation.isValid(value, context); 
    } 
} 

где-то в коде:

MyValidator.setImplementationClass(MyValidatorTwo.class); 

Но есть одна проблема. Скорее всего, экземпляр каждого валидатора создается один раз во время выполнения для одного класса - при первом вызове проверки на объекте этого класса. Изменение реализации вступит в силу только после этого.

Другой способ - хранить значения implementationClass во внешнем классе, например java.util.Properties или класс, который выбирает доступные реализации с некоторым приоритетом.

0

Нет, это невозможно. Если вы хотите, чтобы скрыть свои реализации валидатора из определений общественных ограничений, у вас есть следующие варианты:

  • Обеспечить отображение ограничения XML file и связать его с вашим дистрибутивом. Тем не менее, пользователи ограничения должны будут добавить файл к своему validation.xml.
  • Если вы используете решение DI, такое как CDI или Spring, предоставляете только очень тонкую реализацию валидатора как часть вашего публичного API (возможно, как внутренний класс аннотации) и получаете фактическую реализацию через инъекцию зависимостей
  • Если вы находитесь в Hibernate Validator 5.2 (в настоящее время разрабатываете), ограничители валидации can be registered через файл META-INF/services, который будет именно тем, что вы после этого; Вы даже можете подключить персонализированное определение определения ограничений для реализации других стратегий поиска.
+0

Просто пришло мне в голову, что вы также можете попробовать подключить свой пользовательский 'ConstraintValidatorFactory', который знает, как перейти от открытого интерфейса валидатора к фактической внутренней реализации. Я не уверен, есть ли в библиотеке какой-то код, который проверяет, действительно ли указанный класс является реально доступным. Стоит попробовать. – Gunnar

Смежные вопросы