CDI / Weld

时间:2019-02-12 01:20:12

标签: java configuration cdi weld

对于合成CDI Bean的配置,我有一个有趣的困惑,实际上可能值得进行规格更新。

许多人在这里和其他地方评论了在运行时配置方面缺少CDI的情况。具体地说,诸如实体管理器之类的东西具有有限的实际值,但是为每个对象创建一个注入点,或者仅使用@Dependent范围bean是不现实的。在“实体管理器”案例中,这使得跟踪事务范围变得困难甚至不可能,但是人们可以想象有很多类似的案例。

基本上我想做的是这样的:

InjectionPoint:

@Inject
@SomeQualifier("differentiating value")
ExternalResourceObject resourceObject;

InjectionTarget:

@Produces
@ApplicationScoped
@SomeQualifier("")
public ExternalResourceObject produceResource(SomeQualifier qualifierValue) {
  // Use qualifierValue to produce an instance unique to this particular value
}

在实践中发生的事情是,要访问SomeQualifier,必须使用InjectionPoint,这将使整个生产者都需要@Dependent作用域。此外,限定符必须在参数上定义@Nonbinding,否则生产者将不匹配可能产生的各种配置。

为避免这种情况,我求助于一个CDI插件,该插件接收ProcessInjectionPoint和ProcessType事件,然后在AfterBeanDiscovery中,通过综合创建bean并注入@Configuration带注释的字段来使两者匹配。然后,普通的bean初始化发生在@PostConstruct中,该@PostConstruct会拾取@Configuration字段(如果存在),创建经过适当注释的特定于配置的bean类型,然后容器在需要时将其注入。

这实际上效果很好。稍加小心,装饰器和拦截器甚至可以正确应用,尽管我没有看到很多示例在这种情况下出现在野外。

这是问题的症结所在:

在AfterBeanDiscovery上,有时需要依赖的资源。在普通的CDI bean中,这是在InjectionPoint发现期间发生的,因为枚举点是枚举的。在合成bean的情况下,实际上直到发现所有静态定义的配置对都被枚举之后,才可能知道所需的依赖资源是什么。

当前,我在每个类上使用一种特别命名的静态方法,该方法传递@Configuration参数以询问它需要哪些依赖的注入点,然后将其递归链接到每个后续发现的注入点。该方法特定于我的插件,因此最终超出了CDI规范。 (尽管从技术上讲,整个机制是某种方式)

问题:是否有更好的方法(较少hacky)来处理这些综合配置InjectionPoints的问题?特别是,如果有一种方法可以捕获Bean Not Found类型的事件并针对该特定情况使用适当配置的Bean进行回复(当然,当存在@Configuration属性时),则将不需要这种静态发现方法,但是我在规范中找不到类似的东西。

轻量级专家:这似乎是一个非常普遍的用例,尤其是对于诸如EntityManagers之类的东西,甚至在那种情况下,人们都可以想象连接池是他们自己的依赖CDI资源,而这不会在注入点发现时不为人所知。

这似乎是一种非常合理的方法,只是允许将必要的配置注入到由@Configuration之类的限定符指定的InjectionTarget中。

拥有像本规范中所述的机制将大大减少围绕持久性上下文和其他池化资源的一些样板重复注入点代码,其中许多不一定在容器启动时明确定义。

0 个答案:

没有答案