关于雅加达EE:Java EE6:替代CDI替代

java ee6: override CDI alternative

我正在使用Glassfish 3.1.2.2,java ee6。

我有一个类在其中使用CDI来获取帮助器类的库。我想在一个使用该库的特定项目中重写该CDI依赖关系,并强制该库使用我自己的针对该项目的帮助器类。我可以随意修改该库,但是默认情况下,它应该使用其默认的帮助程序类,以便该库的其他用户的行为不会改变。

这应该是@Alternative CDI模式的完美应用。我为助手类API创建了一个Java接口;库中有一个默认实现,那么我可以在beans.xml中使用标记;在要覆盖其行为的项目中,我将在该特定项目的bean.xml中指定我自己的帮助程序实现。

除非它不起作用。在CDI 1.0(java ee6)库的外部库中,似乎不可能覆盖替代行为。

因此,无论我在外部项目的beans.xml中指定什么,CDI都会继续选择库中定义的bean。

我考虑过通过生产者,但是我没有找到如何获取CDI来将EntityManager作为参数提供给生产者的方式,因此我可以将其传递给帮助者类。在这个项目中,我们通常使用@PersistenceContext注释注入EntityManager。

关于如何覆盖外部项目中的CDI注入的任何想法?


Apache DeltaSpike提供了一个称为全局替代功能的功能,该功能可以绕过那些愚蠢的BDA规则。它已通过许多容器进行了测试,您无需手动关心这些细节。使用OpenWebBeans,您根本不会遇到此问题,某些版本的Weld通过WEB-INF中的bean.xml而不是META-INF支持它。


您可以编写一个可移植的扩展程序来执行此操作。收听ProcessAnnotatedType事件,并用您自己的AnnotatedType替换。您可以使用Apache DeltaSpike BeanBuilder类来帮助解决此问题。


我最后使用的解决方案与LightGuard的建议有关:我具有CDI扩展名,并且按照建议覆盖了processAnnotatedType()。

但是,我没有使用AnnotatedType(我不确定该怎么做)来代替,而是使用此处描述的技术:
http://docs.jboss.org/weld/reference/latest/zh-CN/html/extend.html#d0e4800

然后否决库中定义的bean。

现在默认的实现是否决权,如果我将自己的bean放入应用程序中,那就是CDI选择的实现。

要在Arquillian集成测试中也可以使用此功能,必须将此调用添加到存档中:

1
addAsServiceProvider(Extension.class, <CDI extension class name>.class)

javax.enterprise.inject.spi.Extension资源不需要在Arquillian中生效(请参阅SHRINKWRAP-266)。