我正在使用Glassfish 3.1.2.2,java ee6。
我有一个库,其中一个类使用CDI来获取辅助类。我想在一个我使用该库的特定项目中,覆盖该CDI依赖项并强制库使用我自己的助手类,而不是特定于该项目。我可以随意修改库,但默认情况下它应该使用它的默认助手类,这样对于库的其他用户来说这种行为不会改变。
这应该是@Alternative
CDI模式的完美应用。我为helper类API创建了一个java接口;库中有一个默认实现,然后我可以使用<alternatives>
中的beans.xml
标记;在我想要覆盖行为的项目中,我将在该特定项目的beans.xml中指定我自己的帮助器实现。
除非它不起作用。它是apparently impossible来覆盖CDI 1.0(java ee6)中库外的库的替代行为。
所以无论我在外部项目的beans.xml中指定什么,CDI都会继续选择库中定义的bean。
我考虑过going through a producer但是我没有找到如何让CDI将生成器作为参数提供给生产者,以便我可以将它传递给帮助者类。在这个项目中,我们通常使用@PersistenceContext
注释注入EntityManager。
关于如何从外部项目覆盖CDI注入的任何想法?
答案 0 :(得分:1)
您可以编写一个Portable Extension来执行此操作。收听ProcessAnnotatedType
事件并将AnnotatedType
替换为您自己的事件。您可以使用Apache DeltaSpike BeanBuilder
类来帮助解决这个问题。
答案 1 :(得分:1)
Apache DeltaSpike提供了一个名为global-alternatives的功能,它绕过了那些愚蠢的BDA规则。它已经过很多容器的测试,你没有手动关注细节。使用OpenWebBeans,您根本没有这个问题,并且某些版本的Weld通过WEB-INF中的beans.xml而不是META-INF来支持它。
答案 2 :(得分:0)
我最后使用的解决方案与LightGuard的建议有关:我有CDI扩展,我按照建议覆盖processAnnotatedType()。
然而,我没有替换AnnotatedType
(我不知道怎么做),而是使用那里描述的技术:
http://docs.jboss.org/weld/reference/latest/en-US/html/extend.html#d0e4800
并否决图书馆中定义的bean。
现在默认的实现被否决了,如果我把自己的bean放在我的应用程序中,那就是CDI选择的那个。
要在Arquillian集成测试中使用此功能,您必须将此调用添加到您的存档:
addAsServiceProvider(Extension.class, <CDI extension class name>.class)
javax.enterprise.inject.spi.Extension
资源无需在Arquillian中生效(请参阅SHRINKWRAP-266)。