java ee6:覆盖CDI替代方案

时间:2013-09-02 14:09:09

标签: java-ee glassfish cdi

我正在使用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注入的任何想法?

3 个答案:

答案 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)。