Spring 3.1 Autowiring does not work inside custom constraint validator
Autowiring a service into a validator
Autowired Repository is Null in Custom Constraint Validator
我有一个Spring项目,我想在其中使用Hibernate Validator进行对象验证.基于我在网上阅读的内容和一些论坛,我试图注入验证器如下:
@Bean public Validator validator() { return new LocalValidatorfactorybean().getValidator(); }
但无论我在哪里使用
@Autowired Validator validator;
它采用了Spring的验证器实现而不是Hibernate的验证器.我无法弄清楚如何准确地注入Hibernate验证器并简单地将其自动装配到其他类中,所以我使用了一个便宜的技巧,现在我的Java Config看起来像这样
@Bean public Validator validator() { // ValidatorImpl is Hibernate's implementation of the Validator return new ValidatorImpl(); }
(我真的很感激,如果有人能指出我如何避免以这种Hacky方式获得Hibernate Validator的正确方向)
但是让我们来看看主要问题:
这是自定义验证定义
@Target( { METHOD,FIELD,ANNOTATION_TYPE,CONSTRUCTOR,PARAMETER } ) @Retention(RUNTIME) @Constraint(validatedBy = EmployeeValidator.class) @Documented public @interface EmployeeValidation { String message() default "{constraints.employeeConstraints}"; public abstract Class<?>[] groups() default {}; public abstract Class<? extends Payload>[] payload() default {}; }
我的自定义验证器
public class EmployeeValidator implements ConstraintValidator<EmployeeValidation,Object> { @Autowired private EmployeeService employeeService; @Override public void initialize(EmployeeValidation constraintAnnotation) { //do Something } @Override public boolean isValid(String type,ConstraintValidatorContext context) { return false; } }
在上面的Custom Constraint Validator中,我得到employeeService null.我知道Spring启动时没有实例化ConstraintValidator的任何实现,但我认为添加ValidatorImpl()实际上会解决这个问题.但事实并非如此.
现在我陷入了一个非常hacky的解决方法,我不想继续这样的代码.有人可以帮助我解决我的情况.
附:这些是我在Java Config文件中的导入:
import org.hibernate.validator.HibernateValidator; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.MessageSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; import org.springframework.context.support.ReloadableResourceBundleMessageSource; import org.springframework.core.env.Environment; import org.springframework.validation.Validator; import org.springframework.validation.beanvalidation.LocalValidatorfactorybean; import org.springframework.web.servlet.LocaleResolver; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; import org.springframework.web.servlet.i18n.CookieLocaleResolver; import org.springframework.web.servlet.i18n.LocaleChangeInterceptor; import org.springframework.web.servlet.view.InternalResourceViewResolver;
解决方法
@Bean public Validator validator () { ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class ) .configure().constraintValidatorFactory(new SpringConstraintValidatorFactory(autowireCapablebeanfactory)) .buildValidatorFactory(); Validator validator = validatorFactory.getValidator(); return validator; }
使用SpringConstraintValidatorFactory初始化验证器以便注入工作并将验证器实现提供为Hibernate.class以下列方式工作:
>您的项目将由您选择的图书馆验证
>您的自定义验证器将能够使用Spring的功能,同时通过Hibernate执行验证.
这个怎么运作:
Hibernate的ConstraintValidtorFactory不会初始化任何ConstraintValidator,除非它们被调用但SpringConstraintValidatorFactory通过向它提供AutowireCapablebeanfactory来实现.
编辑
正如@shabyasaschi的一条评论中所提到的,要注入autowireCapablebeanfactory,您可以将方法签名更改为:
Validator validator(final AutowireCapablebeanfactory autowireCapablebeanfactory) {
或者在配置文件中为它添加getter和setter,如下所示:
public AutowireCapablebeanfactory getAutowireCapablebeanfactory() { return autowireCapablebeanfactory; } public void setAutowireCapablebeanfactory(AutowireCapablebeanfactory autowireCapablebeanfactory) { this.autowireCapablebeanfactory = autowireCapablebeanfactory; }