CDI 1.1中注解的bean发现模式的含义
Posted
技术标签:
【中文标题】CDI 1.1中注解的bean发现模式的含义【英文标题】:Meaning of bean discovery mode annotated in CDI 1.1 【发布时间】:2013-08-21 01:09:47 【问题描述】:我正在将应用程序迁移到 Java EE 7 并希望迁移到 CDI 1.1。但我不明白bean-discovery-mode="annotated"
的含义。这
CDI 1.1 specification 不是很有帮助。至少我还没有找到任何有用的段落。我错过了吗?
这个例子与bean-discovery-mode="all"
完美运行并注入LoggingClass
的一个实例:
public class LoggingClass
public Logger logger = Logger.getLogger("ALOGGER");
@Test
public class MMLoggerProducerIT extends Arquillian
@Inject private LoggingClass lc;
但是,如果我从 bean-discovery-mode="all"
更改为 bean-discovery-mode="annotated"
,则容器无法将实例注入字段 lc
。
如何注释LoggingClass
才能正确使用bean-discovery-mode="annotated"
?
【问题讨论】:
我只是猜测,但我认为 '@Named' 或 ''@ManagedBean' 会是候选人? @Mike_Braun Named 只会在 EL 上下文中公开一个 bean,但不会给它一个范围。 ManagedBean 是一个 JSF 注解,CDI 引擎会忽略它。 【参考方案1】:当使用bean-discovery-mode="annotated"
时,仅使用具有bean 定义注释 are discovered 的类。所有其他类都被忽略。 任何作用域类型都是定义注解的 bean。如果在 bean 类上声明了范围类型,则称该 bean 类具有 bean 定义注释 [规范]。 1.1 规范在这里并不完全清楚。仅发现具有@NormalScope
作用域或@Dependent
伪作用域的类、@javax.inject.Singleton
和所有其他@Scope
(伪)作用域are ignored。
请注意,“bean 定义注释”的定义在 CDI 1.2 中发生了变化,现在定义得很好:
定义注解的bean集合包含:
@ApplicationScoped、@SessionScoped、@ConversationScoped 和 @RequestScoped 注释, 所有其他普通范围类型, @Interceptor 和@Decorator 注释, 所有原型注解(即用@Stereotype注解的注解), 和 @Dependent 范围注释。
【讨论】:
【参考方案2】:实际上,bean-discovery-mode="ALL"
会开启对存档中所有类的扫描。这称为“显式存档”。
省略 beans.xml
或设置 bean-discovery-mode="ANNOTATED"
,会使存档成为隐式存档。在这种情况下,容器将扫描带有注解作用域类型的 bean。
这解释了为什么在设置bean-discovery-mode="ANNOTATED"
时不会注入LoggingClass
。如 Java EE 7 教程中所述:
CDI 只能管理和注入在隐式存档中使用范围类型注释的 bean。
编辑:为了绝对清楚,您需要向LoggingClass
添加范围类型。所以是这样的:
@SessionScoped
public class LoggingClass
public Logger logger = Logger.getLogger("ALOGGER");
在 Java EE 7 和 CDI 1.1 中,我们删除了包含 beans.xml
部署描述符以为存档打开 CDI 的要求,使 CDI 1.1 与部署描述符是可选的大多数其他 Java EE API 保持一致。它还删除了是否包含beans.xml
的二进制开/关性质。您可以通过bean-discovery-mode
中的设置来控制容器扫描哪些文件。
在此处查看有关打包 CDI 应用程序的 JavaEE 教程: http://docs.oracle.com/javaee/7/tutorial/cdi-adv001.htm#CACDCFDE
【讨论】:
如果没有beans.xml
,拦截器和装饰器是如何注册和排序的?有办法吗?
@nosuchnick 拦截器可以通过使用@Interceptors
和@Priority
的注释来订购,如in section 54.2.5 here 所述。
它是否描述了如何让@Produces 工作?我必须在 Factory 类上添加注释吗?【参考方案3】:
我也同意@rmuller 的回答形式。但我想指出的是,应用服务器 Payara 和 Wildfly 上仍然存在不同的行为。 请参阅以下示例,其中包含普通的非作用域类但具有 @EJB 注入:
public class SomeClass
@EJB
MyService myService;
...
如果您提供 beans.xml 文件:
.... version="1.2" bean-discovery-mode="annotated"....
Payara 4.1 将不将类 SomeClass 视为 CDI bean,并且不会注入服务 EJB。 我很清楚它的行为如规范中所述。
但 Wildfly 10 将该类视为 CDI bean 并注入了预期之外的服务 EJB。要使其正常工作, beans.xml 文件应如下所示:
.... version="1.2" bean-discovery-mode="all"....
令人惊讶的是,两个最常见的应用程序服务器在行为上是不同的。
【讨论】:
以上是关于CDI 1.1中注解的bean发现模式的含义的主要内容,如果未能解决你的问题,请参考以下文章