【问题标题】:Meaning of bean discovery mode annotated in CDI 1.1CDI 1.1中注解的bean发现模式的含义
【发布时间】: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 引擎会忽略它。

标签: dependency-injection cdi java-ee-7


【解决方案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"....
    

    令人惊讶的是,两个最常见的应用程序服务器在行为上是不同的。

    【讨论】:

      猜你喜欢
      • 2021-05-06
      • 1970-01-01
      • 2015-06-14
      • 2013-11-24
      • 2019-03-03
      • 1970-01-01
      • 2014-04-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多