【发布时间】:2019-09-24 21:10:44
【问题描述】:
我正在使用 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);
对于我的对象:
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;
【问题讨论】:
-
您可能需要发布更多代码,
MyValidator未知,您要在哪里自动连接MyValidator? -
我正在制作自己的验证器——我还有其他验证器在工作,但这个需要注入的 Spring 服务。我看到了问题 - 验证器来自工厂,它似乎必须“感知 Spring”......添加更多代码