Autowired 在自定义约束验证器中给出 Null 值 [英] Autowired gives Null value in Custom Constraint validator

查看:42
本文介绍了Autowired 在自定义约束验证器中给出 Null 值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对 Spring 完全陌生,我已经查看了一些关于 SO 的答案以解决所提出的问题.以下是链接:

Spring 3.1 自动装配在内部不起作用自定义约束验证器

将服务自动装配到验证器

自定义约束验证器中的自动装配存储库为空

我有一个 Spring 项目,我想在其中使用 Hibernate Validator 进行对象验证.根据我在网上和几个论坛上阅读的内容,我尝试按如下方式注入验证器:

@Bean公共验证器验证器(){返回新的 LocalValidatorFactoryBean().getValidator();}

但无论我在哪里使用

@Autowired验证器验证器;

它采用 Spring 的验证器实现而不是 Hibernate 的验证器.我不知道如何准确地注入 Hibernate 验证器并简单地将它自动连接到其他类,所以我使用了一个便宜的技巧,现在我的 Java 配置看起来像这样

@Bean公共验证器验证器(){//ValidatorImpl 是 Hibernate 对 Validator 的实现返回新的 ValidatorImpl();}

(如果有人能真正为我指明如何避免以这种 Hacky 方式获取 Hibernate Validator 的正确方向,我将不胜感激)

但是让我们来看看这里的主要问题:

这里是自定义验证定义

@Target( { 方法, 字段, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER } )@保留(运行时间)@Constraint(validatedBy = EmployeeValidator.class)@记录公共@interface EmployeeValidation {String message() 默认{constraints.employeeConstraints}";public abstract Class[] groups() default {};公共抽象类[] payload() 默认{};}

我的自定义验证器

public class EmployeeValidator 实现了 ConstraintValidator{@自动连线私有 EmployeeService 员工服务;@覆盖公共无效初始化(员工验证约束注释){//做一点事}@覆盖公共布尔 isValid(字符串类型,ConstraintValidatorContext 上下文){返回假;}}

在上面的自定义约束验证器中,我得到了employeeService null.我知道在 Spring 启动时没有实例化 ConstraintValidator 的任何实现,但我认为添加 ValidatorImpl() 实际上会解决这个问题.但它没有.

现在我遇到了一个非常棘手的解决方法,我不想继续使用这样的代码.有人可以帮助我解决我的情况.

附言这些是我在 Java 配置文件中的导入:

import org.hibernate.validator.HibernateValidator;导入 org.springframework.beans.factory.annotation.Autowired;导入 org.springframework.context.MessageSource;导入 org.springframework.context.annotation.Bean;导入 org.springframework.context.annotation.ComponentScan;导入 org.springframework.context.annotation.Configuration;导入 org.springframework.context.annotation.PropertySource;导入 org.springframework.context.support.ReloadableResourceBundleMessageSource;导入 org.springframework.core.env.Environment;导入 org.springframework.validation.Validator;导入 org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;导入 org.springframework.web.servlet.LocaleResolver;导入 org.springframework.web.servlet.ViewResolver;导入 org.springframework.web.servlet.config.annotation.EnableWebMvc;导入 org.springframework.web.servlet.config.annotation.InterceptorRegistry;导入 org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;导入 org.springframework.web.servlet.i18n.CookieLocaleResolver;导入 org.springframework.web.servlet.i18n.LocaleChangeInterceptor;导入 org.springframework.web.servlet.view.InternalResourceViewResolver;

解决方案

我希望这个解决方案能帮助到某人:

@Bean公共验证器验证器 () {ValidatorFactory 验证器工厂 = Validation.byProvider( HibernateValidator.class ).configure().constraintValidatorFactory(new SpringConstraintValidatorFactory(autowireCapableBeanFactory)).buildValidatorFactory();验证器验证器 = validatorFactory.getValidator();返回验证器;}

使用 SpringConstraintValidatorFactory 初始化验证器,以便注入工作并提供验证器实现为 Hibernate.class 以下列方式工作:

  1. 您的对象将由您选择的库进行验证
  2. 您的自定义验证器将能够使用 Spring 的功能,同时让 Hibernate 执行验证.

工作原理:Hibernate 的 ConstraintValidatorFactory 不会初始化任何 ConstraintValidators 除非它们被调用,但是 SpringConstraintValidatorFactory 通过给它 AutowireCapableBeanFactory 来实现.>

编辑

正如@shabyasaschi 在其中一条评论中提到的,要注入 autowireCapableBeanFactory,您可以将方法签名更改为:

Validator 验证器(最终 AutowireCapableBeanFactory autowireCapableBeanFactory){

或者在配置文件中为它添加getter和setter如下:

public AutowireCapableBeanFactory getAutowireCapableBeanFactory() {返回 autowireCapableBeanFactory;}公共无效 setAutowireCapableBeanFactory(AutowireCapableBeanFactory autowireCapableBeanFactory) {this.autowireCapableBeanFactory = autowireCapableBeanFactory;}

I am totally new to Spring and I have looked in to a few answers on SO for the asked problem. Here are the links:

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

I have a Spring project in which I want to use Hibernate Validator for an object validation. Based on what I read online and a few forums I tried to inject validator as follows:

@Bean
  public Validator validator() {
    return new LocalValidatorFactoryBean().getValidator();
  }

But wherever I was using

@Autowired
Validator validator;

It was taking Spring's validator implementation instead of the Hibernate's validator. I couldn't figure out how to exactly inject Hibernate validator and simply Autowire it across other classes so I used a cheap trick, now my Java Config looks like this

@Bean
      public Validator validator() {
        // ValidatorImpl is Hibernate's implementation of the Validator
        return new ValidatorImpl();
      }

(I would really appreciate if someone can actually point me into the right direction on how to avoid getting Hibernate Validator in this Hacky way)

But lets come to the main issue here:

Here is custom validation definition

@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 {};
}

My Custom Validator

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;
}
}

In the above Custom Constraint Validator I get the employeeService null. I know that any implementations of ConstraintValidator are not instantiated when Spring is starting up but I thought adding the ValidatorImpl() will actually fix that. But it didn't.

Now I am stuck with a really hacky workaround and I do not want to continue with a code like that. Can someone please help me with my situation.

P.S. These are my imports in the Java Config file:

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; 

解决方案

I hope the solution will help someone:

@Bean
public Validator validator () {

    ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class )
        .configure().constraintValidatorFactory(new SpringConstraintValidatorFactory(autowireCapableBeanFactory))
        .buildValidatorFactory();
    Validator validator = validatorFactory.getValidator();

    return validator;
}

Initializing the validator with SpringConstraintValidatorFactory so that injection works and providing the validator implementation to be Hibernate.class works in the following manner:

  1. Your objects will be validated by the library of your choice
  2. Your custom validators will be able to use Spring's functionality while having validation to be executed by Hibernate.

How it works: Hibernate's ConstraintValidatorFactory does not initialize any ConstraintValidators unless they are called but SpringConstraintValidatorFactory does by giving AutowireCapableBeanFactory to it.

EDIT

As mentioned in one of the comments by @shabyasaschi To inject autowireCapableBeanFactory you can change the method signature as:

Validator validator(final AutowireCapableBeanFactory autowireCapableBeanFactory) {

or add getter and setter for it in the config file as follows:

public AutowireCapableBeanFactory getAutowireCapableBeanFactory() {
        return autowireCapableBeanFactory;
}

public void setAutowireCapableBeanFactory(AutowireCapableBeanFactory autowireCapableBeanFactory) {
        this.autowireCapableBeanFactory = autowireCapableBeanFactory;
}

这篇关于Autowired 在自定义约束验证器中给出 Null 值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆