通过抽象类或接口进行自定义bean验证

时间:2014-11-06 19:21:08

标签: java bean-validation

让我们考虑以下示例,我正在通过新的注释类型创建自定义bean验证约束:

@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();

}

我的问题是:can MyBastractOrInterfaceValidator类可以是抽象类还是接口?如何控制该接口或抽象类的哪个实现用于验证注释所在的元素?

2 个答案:

答案 0 :(得分:0)

请参阅http://docs.oracle.com/javaee/7/api/javax/validation/Constraint.html

首先,请注意validatedByClass<? 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或选择具有某些优先级的可用实现的类。

答案 1 :(得分:0)

不,那是不可能的。如果要从公共约束定义中隐藏验证器实现,可以使用以下选项:

  • 提供约束映射XML file并将其与您的发行版捆绑在一起。但是,约束的用户必须将文件添加到他们的validation.xml
  • 如果您使用的是DI解决方案,例如CDI或Spring,请提供一个非常纤薄的验证器实现作为公共API的一部分(可能作为注释的内部类)并通过依赖注入获取实际实现
  • 如果您使用的是Hibernate Validator 5.2(目前正在开发中),则通过META-INF / services文件约束验证器can be registered,这正是您所追求的;您甚至可以插入自定义约束定义贡献者来实现其他查找策略