3

我正在使用 Glassfish 3.1.2.2、java ee6。

我有一个库,其中一个类使用 CDI 来获取一个帮助类。我想在一个使用该库的特定项目中覆盖该 CDI 依赖项并强制该库使用我自己的帮助程序类,而不是特定于该项目。我可以随意修改库,但默认情况下它应该使用其默认的帮助程序类,这样库的其他用户的行为就不会改变。

这应该是@AlternativeCDI模式的完美应用。我为帮助类 API 制作了一个 java 接口;库中有一个默认实现,然后我可以使用;<alternatives>中的标签 beans.xml在我想要覆盖行为的项目中,我会在该特定项目的 beans.xml 中指定我自己的帮助程序实现。

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

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

我考虑过通过生产者,但我没有找到如何让 CDI 将 EntityManager 作为参数提供给生产者,以便我可以将其传递给辅助类。@PersistenceContext在这个项目中,我们通常使用注解注入 EntityManager 。

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

4

3 回答 3

1

Apache DeltaSpike 提供了一个名为 global-alternatives 的功能,它绕过了那些愚蠢的 BDA 规则。它已经过大量容器的测试,您不必手动关心细节。使用 OpenWebBeans,您根本不会遇到这个问题,并且某些版本的 Weld 通过 WEB-INF 中的 beans.xml 而不是 META-INF 来支持它。

于 2013-09-08T18:04:50.397 回答
1

您可以编写一个便携式扩展来执行此操作。收听ProcessAnnotatedType事件并AnnotatedType用您自己的替换。您可以使用 Apache DeltaSpikeBeanBuilder类来帮助解决这个问题。

于 2013-09-03T02:34:22.120 回答
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)。

于 2013-09-03T08:48:04.227 回答