hibernate-validatior-cdi:为何ConstraintValidator在weld-se容器中不是托管实例
问题根因
默认情况下,JPA提供者(如Hibernate)使用的ConstraintValidatorFactory会自行实例化校验器,不走Weld的CDI容器生命周期管理,因此校验器类里标注@Inject的依赖无法完成注入,直接触发空指针异常。
解决步骤
1. 自定义集成CDI的校验器工厂
实现ConstraintValidatorFactory接口,从Weld容器中获取校验器实例:
public class CdiConstraintValidatorFactory implements ConstraintValidatorFactory { private final Instance<Object> instance; // 注入CDI的Instance实例,用于获取容器内的Bean @Inject public CdiConstraintValidatorFactory(Instance<Object> instance) { this.instance = instance; } @Override public <T extends ConstraintValidator<?, ?>> T getInstance(Class<T> key) { return instance.select(key).get(); } @Override public void releaseInstance(ConstraintValidator<?, ?> instance) { this.instance.destroy(instance); } }
2. 配置JPA使用自定义校验器工厂
在persistence.xml的persistence-unit节点下添加对应属性:
<!-- Java EE/Jakarta EE 8及以下版本用这个属性 --> <property name="javax.persistence.validation.factory" value="com.foo.bar.validation.CdiConstraintValidatorFactory"/> <!-- Jakarta EE 9+版本用这个属性 --> <!-- <property name="jakarta.persistence.validation.factory" value="com.foo.bar.validation.CdiConstraintValidatorFactory"/> -->
3. 补充CDI作用域注解
给MyValidator类添加@Dependent注解,让CDI容器识别并管理该类的生命周期,同时确认MyDao已经正确标注@ApplicationScoped等CDI作用域注解,可被容器正常实例化。
4. 测试上下文检查
确认测试类已添加@EnableWeld注解,且通过@AddBeanClasses或自动扫描机制,把MyValidator、MyDao、CdiConstraintValidatorFactory都纳入了测试上下文的Bean管理范围。
内容的提问来源于stack exchange,提问作者duschata
相关产品推荐
相关产品推荐

