在约束验证器中使用Guice进行依赖注入 [英] Dependency injection using Guice within Constraint validator
问题描述
我有一个在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实例(请参阅约束验证器)。
所以您基本上有两种可能性:
-
实现自定义
ConstraintValidatorFactory
,这在链接的文档中有描述,在该工厂中,可以访问guice注入器以获取ServiceA
并将其传递给构造函数。 -
删除
公共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:
Implement a custom
ConstraintValidatorFactory
, this is described in the linked documentation, and in that factory, get access to the guice injector to get theServiceA
and pass it to the constructor.Remove the
public MyValidator(ServiceA serviceA)
constructor and try to initialize the reference toServiceA
from within thepublic 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屋!