如何在JSR-303自定义验证器中解决依赖关系

时间:2017-04-10 15:16:47

标签: java hibernate validation bean-validation

假设有一个像这样的自定义验证注释

@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {ThirdPartyConstraintValidator.class}) 
@Documented
public @interface ThirdPartyConstraint {
   String message() default "Invalid";

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

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

需要其他服务的相应Validator

public class ThirdPartyConstraintValidator implements ConstraintValidator<ThirdPartyConstraint, Pojo> {

  private ThirdPartyService thirdPartyService;

  @Override
  public void initialize(ThirdPartyConstraint thirdPartyConstraint) {}

  @Override
  public boolean isValid(Pojo pojo, ConstraintValidatorContext constraintValidatorContext) {
    return thirdPartyService.isValid(pojo);
  }

  public void setThirdPartyService(ThirdPartyService thirdPartyService) {
    this.thirdPartyService = thirdPartyService;
  }
}

使用Hibernate实现初始化验证上下文

ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();

// and then some bean is validated
validator.validate(new Pojo());

在后台validate方法调用class.newInstance()以获取验证程序实现。因此,在ThirdPartyConstraintValidator的情况下,永远不会注入依赖项ThirdPartyService

在没有任何框架的情况下使用ThirdPartyService时,有没有办法通过setter或构造函数将ThirdPartyConstraintValidator注入ValidationFactory

更新

在@matthias回答之后,我更新了我的ValidatorFactory以初始化其中的ThirdPartyConstraintValidator

public <T extends ConstraintValidator<?, ?>> T getInstance(Class<T> aClass) {
   if (ThirdPartyConstraintValidator.class.equals(aClass)) {
      ThirdPartyConstraintValidator thirdPartyConstraintValidator = new ThirdPartyConstraintValidator();
      thirdPartyConstraintValidator.setThirdPartyService(new ThirdPartyService());
      return (T) thirdPartyConstraintValidator;
   }
   return null;
}

1 个答案:

答案 0 :(得分:2)

您可以实现自定义ConstraintValidatorFactory来设置依赖关系。

请参阅BeanVal SpecHibernate Validator Doc

Validator v = Validation.byDefaultProvider().configure()
        .constraintValidatorFactory(new MyConstraintValidatorFactory())
        .buildValidatorFactory()
        .getValidator();

class MyConstraintValidatorFactory implements ConstraintValidatorFactory {

    public <T extends ConstraintValidator<?, ?>> T getInstance(final Class<T> arg0) {
        //do your stuff to set dependencies
        ...
    }

    public void releaseInstance(final ConstraintValidator<?, ?> arg0) {
        ...
    }
}