将Spring依赖项注入ConstrantValidator

问题描述 投票:-1回答:1

我正在使用Bean验证。我有一个自定义验证器@MyValidator,需要使用注入的Spring托管DAO对象查找值。如何获得此权限? Spring不会将DAO注入到我的“ MyValidator”对象中。

@Component
public class CodeListValidator implements ConstraintValidator<CodeList, String> {
    @Autowired
    private ICodeListCommonService codeListCommonService;

    private CodeListEnum codeListID;

    @Override
    public void initialize(CodeList constraintAnnotation) {
        this.codeListID = constraintAnnotation.value();
    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        return codeListCommonService.doesCodeEntityExistForCodeList(codeListID.getDbCodeListId(), value, ProviderConstants.CODE_LIST_STATUS_ACTIVE);
    }
}

“ codeListCommonService”为空。这是因为Spring没有创建类-但是如何使它与Spring AoP一起使用?

此验证器的用法如下:


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

        MyObject validateMe = new MyObject();

        Set<ConstraintViolation<MyObject>> constraintViolations = validator.validate(validateMe);

对于MyObject:

public class MyObject {
   @Size(max = 1)
   @CodeList(CodeListEnum.CARTYPE)
   public String carType;
}

因此,当验证器运行时,它会处理注释...我只需要将服务注入到我制作的CodeListValidator中,就可以对它进行数据库查找,以对照“有效汽车类型值”的数据库列表来验证该值。 。

编辑:解决方案:

[玩弄了使Spring意识化的工厂的想法-与现有代码的过多集成。

似乎最好的解决方案(在这里可行)是使Spring服务将ApplicationContext存储在静态方法中,以便“非Spring管理的” bean可以到达它们。

因此是一项新服务:

@Service
public class SpringApplicationContextService implements ISpringApplicationContextService, ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }
}

然后任何验证器或非Spring Bean都可以通过以下方式获取Spring Bean:

public class CodeListValidator implements ConstraintValidator<CodeList, String> {
    @Autowired
    private ICodeListCommonService codeListCommonService;

    private CodeListEnum codeListID;

    @Override
    public void initialize(CodeList constraintAnnotation) {
        this.codeListID = constraintAnnotation.value();
    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        ICodeListCommonService codeListCommonService = SpringApplicationContextService.getApplicationContext().getBean(ICodeListCommonService.class);
        return codeListCommonService.doesCodeEntityExistForCodeList(codeListID.getDbCodeListId(), value, ProviderConstants.CODE_LIST_STATUS_ACTIVE);
    }
}

并且,当然,所有这些的原因(在此应用中已使用了数十次):

    @CodeList(CodeListEnum.EMAIL_OPT_OUT_FLAG)
    public String emailOptOutFlag;

    @CodeList(CodeListEnum.CLEARING_HOUSE)
    public String clearingHouse;

spring bean-validation
1个回答
0
投票

@AutowiredConstraintValidator实现中正常工作的最小设置是将此bean放入Spring @Configuration

    @Bean
    public Validator defaultValidator() {
        return new LocalValidatorFactoryBean();
    }

这允许将包括ApplicationContext在内的所有bean直接注入ConstraintValidator

@Constraint(validatedBy = DemoValidator.class)
public @interface DemoAnnotation {
    // ...
    Class<?> beanClass();
}

public class DemoValidator implements ConstraintValidator<DemoAnnotation, String> {

    private final ApplicationContext applicationContext;

    private Object bean;

    @Autowired
    public DemoValidator(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    @Override
    public void initialize(DemoAnnotation constraint) {
        Class<?> beanClass = constraint.beanClass();
        bean = applicationContext.getBean(beanClass);
    }

    @Override
    public boolean isValid(String obj, ConstraintValidatorContext context) {
        return !obj.isEmpty();
    }
}

Demo

对于一个非常灵活的验证解决方案,我建议Jakub Jirutka's Bean Validator utilizing Spring Expression Language (SpEL)允许使用以下内容:

public class Sample {

    @SpELAssert("@myService.calculate(#this) > 42")
    private int value;
}
© www.soinside.com 2019 - 2024. All rights reserved.