我想让 CDI“挑选”一个替代类作为接口(interface)的实现。
虽然 EAR 中的所有内容都是 bundle ,但替代实现将在 war 文件中,其余部分(注入(inject)接口(interface)的类、接口(interface)、接口(interface)的“默认”实现)将在 ejb jar 中。
这里有一些代码来说明它:
EJB 模块:
public interface I {}
public class C implements I {}
public class A {
@Inject I var
public void test() {
System.out.println(var instanceof C); // I want to have here as Result: false
}
}
WAR 模块:
@Alternative
public class D implements I {}
在 war 文件中设置 beans.xml 没有帮助..
最佳答案
使用您所描述的结构,无法获得所需的注入(inject)。
EJB 类加载器永远无法访问 WAR 中的类,因此注入(inject)永远不会考虑替代实现。
如果您愿意更改 EAR 结构,将备选方案 (D) 与适当的 beans.xml
一起放置在 lib/jar 中,那么一个解决方案是可能的。 D 类将对您的 EJB 和 WAR 可见,并且注入(inject)应按需要进行。
编辑
我在这里描述的您发布的解决方案几乎可以正常工作。
EAR
- ejb-module-1.jar
- A.class (@Inject I)
- I.class
- C.class (@Stateless implements I)
- META-INF/beans.xml
- ejb-module-2.jar
- D.class (@Alternative @Stateless implements I)
- META-INF/beans.xml (<alternatives><class>D</class></alternative>)
- app.war
- calls A.test()
- WEB-INF/beans.xml
唯一的问题是您错放了 beans.xml
替代声明。
CDI 规范(1.1,但也适用于以前的实现)在第 5.1 章指出:
An alternative is not available for injection, lookup or EL resolution to classes or JSP/JSF pages in a module unless the module is a bean archive and the alternative is explicitly selected in that bean archive.
换句话说,您必须在使用该 bean 的类的同一模块中选择替代项。
这是修改后的(和工作中的)结构:
EAR
- ejb-module-1.jar
- A.class (@Inject I)
- I.class
- C.class (@Stateless implements I)
- META-INF/beans.xml (<alternatives><class>D</class></alternative>)
- ejb-module-2.jar
- D.class (@Alternative @Stateless implements I)
- META-INF/beans.xml (empty <beans></beans>)
- app.war
- calls A.test()
- WEB-INF/beans.xml (empty <beans></beans>)
还请记住,虽然对于标准 bean,替代选择仅适用于在 beans.xml
中声明替代选择的模块,但事实并非如此对于 EJB。因此,您的 D
替代方案(即 @Stateless
)对整个应用程序都有效。
关于java - 如何将带有 CDI 的 @Alternative 从 WAR 注入(inject)到 EJB 模块中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17401985/