在约束验证器中使用Guice进行依赖注入 [英] Dependency injection using Guice within Constraint validator

查看:118
本文介绍了在约束验证器中使用Guice进行依赖注入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个在ConstraintValidator的实现中注入一个类的用例。
我正在使用Google guice进行依赖性注入,目前无法注入验证器中。



我的方案的简化形式



内部模块:

  @提供
@Singleton
public ServiceA getServiceA(){
return new ServiceA();
}

约束验证器:

 公共类MyValidator实现ConstraintValidator< ValidS,List< String>>。 {

私人最终服务A服务A;

@Inject
public MyValidator(ServiceA serviceA){
this.serviceA = serviceA;
}
@Override
public void initialize(final ValidS validS){
}

@Override
public boolean isValid(final List<字符串> sList,最终的ConstraintValidatorContext ConstraintValidatorContext){
System.out.println(serviceA.testInjection());
//验证码
}


}

编辑:
添加异常消息:

  HV000064:无法实例化ConstraintValidator:class com。 validate.MyValidator。 
javax.validation.ValidationException:HV000064:无法实例化ConstraintValidator:类com.validation.MyValidator。 org.hibernate.validator.internal.util.privilegedactions.NewInstance.run(NewInstance.java:51)〜[hibernate-validator-5.0.1.Final.jar:5.0.1.Final]中的

在org.hibernate.validator.internal.util.ReflectionHelper.run(ReflectionHelper.java:671)〜[hibernate-validator-5.0.1.Final.jar:5.0.1.Final]
在org.hibernate .validator.internal.util.ReflectionHelper.newInstance(ReflectionHelper.java:219)〜[hibernate-validator-5.0.1.Final.jar:5.0.1.Final]
,位于org.hibernate.validator.internal。 engine.constraintvalidation.ConstraintValidatorFactoryImpl.getInstance(ConstraintValidatorFactoryImpl.java:34)〜[hibernate-validator-5.0.1.Final.jar:5.0.1.Final]
at org.hibernate.validator.internal.engine.constraintvalidation .ConstraintValidatorManager.createAndInitializeValidator(ConstraintValidatorManager.java:141)〜[hibernate-validator-5.0.1.Final.jar:5.0.1.Final]
,位于org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager。 getInitialized Validator(ConstraintValidatorManager.java:101)〜[hibernate-validator-5.0.1.Final.jar:5.0.1.Final]
at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateConstraints(ConstraintTree .java:125)〜[hibernate-validator-5.0.1.Final.jar:5.0.1.Final]
在org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateConstraints(ConstraintTree.java: 91)〜[hibernate-validator-5.0.1.Final.jar:5.0.1.Final]
at org.hibernate.validator.internal.metadata.core.MetaConstraint.validateConstraint(MetaConstraint.java:85)〜 [hibernate-validator-5.0.1.Final.jar:5.0.1.Final]
at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraint(ValidatorImpl.java:478)〜[hibernate-validator- 5.0.1.Final.jar:5.0.1.Final]
,位于org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForDefaultGroup(ValidatorImpl.java:424)〜[hibernate-validator-5.0.1.Final .jar:5.0.1.Final]
在org.hibernate.valid ator.internal.engine.ValidatorImpl.validateConstraintsForCurrentGroup(ValidatorImpl.java:388)〜[hibernate-validator-5.0.1.Final.jar:5.0.1.Final]
在org.hibernate.validator.internal.engine .ValidatorImpl.validateInContext(ValidatorImpl.java:340)〜[hibernate-validator-5.0.1.Final.jar:5.0.1.Final]
at org.hibernate.validator.internal.engine.ValidatorImpl.validate( ValidatorImpl.java:158)〜[hibernate-validator-5.0.1.Final.jar:5.0.1.Final]
在com.MyClass.validate(MyClass.java:48)


解决方案

您的自定义验证器无法被Hibernate实例化,因为Hibernate希望验证器具有no arg构造函数(休眠文档)


Hibernate Validator提供的默认ConstraintValidatorFactory要求公共无参nstructor实例化ConstraintValidator实例(请参阅约束验证器)。


所以您基本上有两种可能性:


  1. 实现自定义 ConstraintValidatorFactory ,这在链接的文档中有描述,在该工厂中,可以访问guice注入器以获取 ServiceA 并将其传递给构造函数。


  2. 删除公共MyValidator(ServiceA serviceA)构造函数,并尝试从 public void initialize(final ValidS validS) ServiceA 的引用>方法。


要获得注射器,您可以执行以下操作(这是没有好的代码,但是您需要以某种方式访问​​注射器。)要存储您的注射器引用,您可以使用Singleton-在这里,我通过使用枚举来实现它:

 公共枚举GlobalInjector {
实例;
私人喷油器喷油器;
public Injector getInjector(){
返回注射器;
}
public void setInjector(注射器注入器){
this.injector =注射器;
}
}

我不知道您如何初始化guice,但是您可能有这样的代码,因此添加代码来存储注射器:

 注射器注入器= Guice.createInjector(new ConfigurationModule( )); 
GlobalInjector.INSTANCE.setInjector(injector);

然后您的initialize方法如下:

  @Override 
public void initialize(final ValidS validS){
注入器注入器= GlobalInjector.INSTANCE.getInjector();
if(null!=喷射器){
serviceA =喷射器.getInstance(ServiceA.class);
}
}

不要忘记检查 GlobalInjector.INSTANCE.getInjector(); 返回不为空,并且在调用validate方法时,请确保 serviceA 不为空。 / p>

注意:我个人不喜欢将注入器存储为全局变量(由单例伪装)的想法,但是目前,我还没有更好的主意。此代码未经测试,所以我希望它们都能按预期工作。


I have a use case of injecting a class inside an implementation of ConstraintValidator. I'm using Google guice for Dependency injection and am currently unable to inject inside the validator.

Simplified form of my scenario

Inside Module:

@Provides
@Singleton
public ServiceA getServiceA() {
        return new ServiceA();
}

The constraint validator:

public class MyValidator implements ConstraintValidator<ValidS,List<String>> {

    private final ServiceA serviceA;

    @Inject
    public MyValidator(ServiceA serviceA) {
         this.serviceA = serviceA;
    }
    @Override
    public void initialize(final ValidS validS) {
    }

    @Override
    public boolean isValid(final List<String> sList, final ConstraintValidatorContext constraintValidatorContext) {
        System.out.println(serviceA.testInjection());
        //validation code
    }


}

Edit: Adding the exception message:

HV000064: Unable to instantiate ConstraintValidator: class com.validation.MyValidator.
javax.validation.ValidationException: HV000064: Unable to instantiate ConstraintValidator: class com.validation.MyValidator.
    at org.hibernate.validator.internal.util.privilegedactions.NewInstance.run(NewInstance.java:51) ~[hibernate-validator-5.0.1.Final.jar:5.0.1.Final]
    at org.hibernate.validator.internal.util.ReflectionHelper.run(ReflectionHelper.java:671) ~[hibernate-validator-5.0.1.Final.jar:5.0.1.Final]
    at org.hibernate.validator.internal.util.ReflectionHelper.newInstance(ReflectionHelper.java:219) ~[hibernate-validator-5.0.1.Final.jar:5.0.1.Final]
    at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorFactoryImpl.getInstance(ConstraintValidatorFactoryImpl.java:34) ~[hibernate-validator-5.0.1.Final.jar:5.0.1.Final]
    at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager.createAndInitializeValidator(ConstraintValidatorManager.java:141) ~[hibernate-validator-5.0.1.Final.jar:5.0.1.Final]
    at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager.getInitializedValidator(ConstraintValidatorManager.java:101) ~[hibernate-validator-5.0.1.Final.jar:5.0.1.Final]
    at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateConstraints(ConstraintTree.java:125) ~[hibernate-validator-5.0.1.Final.jar:5.0.1.Final]
    at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateConstraints(ConstraintTree.java:91) ~[hibernate-validator-5.0.1.Final.jar:5.0.1.Final]
    at org.hibernate.validator.internal.metadata.core.MetaConstraint.validateConstraint(MetaConstraint.java:85) ~[hibernate-validator-5.0.1.Final.jar:5.0.1.Final]
    at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraint(ValidatorImpl.java:478) ~[hibernate-validator-5.0.1.Final.jar:5.0.1.Final]
    at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForDefaultGroup(ValidatorImpl.java:424) ~[hibernate-validator-5.0.1.Final.jar:5.0.1.Final]
    at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForCurrentGroup(ValidatorImpl.java:388) ~[hibernate-validator-5.0.1.Final.jar:5.0.1.Final]
    at org.hibernate.validator.internal.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:340) ~[hibernate-validator-5.0.1.Final.jar:5.0.1.Final]
    at org.hibernate.validator.internal.engine.ValidatorImpl.validate(ValidatorImpl.java:158) ~[hibernate-validator-5.0.1.Final.jar:5.0.1.Final]
    at com.MyClass.validate(MyClass.java:48) 

解决方案

Your custom validator cannot be instantiated by Hibernate, as Hibernate expects the validator to have a no arg constructor (hibernate docs):

The default ConstraintValidatorFactory provided by Hibernate Validator requires a public no-arg constructor to instantiate ConstraintValidator instances (see The constraint validator).

So you basically have two possibilities:

  1. Implement a custom ConstraintValidatorFactory, this is described in the linked documentation, and in that factory, get access to the guice injector to get the ServiceA and pass it to the constructor.

  2. Remove the public MyValidator(ServiceA serviceA) constructor and try to initialize the reference to ServiceA from within the public void initialize(final ValidS validS)method. Here you need to get the guice injector as well.

To get the injector you could do the following (this is no nice code, but somehow you need to get access to the injector). To store your injector reference you could use a Singleton - here I implement it by using an enum:

public enum GlobalInjector {
  INSTANCE;
  private Injector injector;
  public Injector getInjector() {
    return injector;
  }
  public void setInjector(Injector injector) {
    this.injector = injector;
  }      
}

I do not know how you initialize guice, but you probably have some code like this, so add the code to store the injector:

Injector injector = Guice.createInjector(new ConfigurationModule());
GlobalInjector.INSTANCE.setInjector(injector);

Then your initialize method would look like:

@Override
public void initialize(final ValidS validS) {
  Injector injector = GlobalInjector.INSTANCE.getInjector();
  if(null != injector) {
    serviceA = injector.getInstance(ServiceA.class);
  }
}

Do not forget to check if GlobalInjector.INSTANCE.getInjector(); returns not null, and when your validate method is called, make sure that serviceA is not null.

Note: personally I do not like the idea of storing the injector as a global variable (disguised by a singleton), but at the moment, I have no better idea. This code is not tested, so I hope it all works as intended.

这篇关于在约束验证器中使用Guice进行依赖注入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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