我想让CDI“选择”替代类作为接口的实现。
虽然EAR中的所有内容都是捆绑包,但是替代实现将在war文件中,其余的(注入接口的类,接口,接口的“默认”实现)将在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没有帮助..
答案 0 :(得分:6)
根据您描述的结构,无法获得所需的注射。
EJB类加载器永远无法访问WAR内的类,因此注入永远不会考虑替代实现。
如果您愿意更改EAR结构,将备选项(D)放在lib / jar中,以及appropriare beans.xml
,则可以使用解决方案。 D类将对您的EJB和WAR可见,并且注入应按照需要进行。
我发布的解决方案,我在这里所说的,几乎正在运作。
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章中指出:
替代品不适用于注射,查找或EL分辨率 除非模块是bean,否则模块中的类或JSP / JSF页面 存档和替代是在该bean中明确选择的 档案
换句话说,您必须在使用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
)对整个应用程序都有效。
答案 1 :(得分:2)
自CDI 1.1以来。您可以使用@Priority,以便在全局范围内发现您的替代方案 - 请参阅此处Dependency injection and programmatic lookup
如果您使用@Priority,则无需在beans.xml中声明替代方法 - 请参阅此处Using Alternatives in CDI Applications