为什么CDI中需要beans.xml?

   |       CDI Weld

我看到一些人想知道为什么CDI需要在每个bean存档中包含beans.xml文件。如果没有要声明的拦截器或装饰器,为什么还需要一个空文件呢?

嗯,关于CDI有两件事我们需要记住

  • CDI不要求Java类进行任何特殊声明就可以注入 - 这是对的,根本不需要任何注解或XML声明!
  • CDI没有定义任何特殊的模块类型 - CDI beans可以部署在库jar、EJB jar、war、rar或JVM类路径目录中。

CDI规范将模块中识别bean的过程称为bean发现

因此,类路径中可能有很多类是bean!我们不希望容器在启动时扫描所有这些类,并为它们中的每一个构建内部元模型。这可能会使bean发现变得非常缓慢。

但还有一个原因我们需要让用户能够控制哪些类可用于注入。我们不希望类路径中的每个类都可能匹配注入点,包括那些从未打算注入到任何地方的类。这将迫使开发人员更频繁地使用限定符来区分注入点。

因此,我们有两个选择。我们可以让开发人员

  1. 显式排除不包含bean的模块,或者
  2. 显式声明包含bean的模块。

我认为很明显,第二个选项是一个更好的选择。因此,CDI有bean存档的概念。bean存档只是一个包含名为beans.xml在元数据目录中的文件的模块。容器在bean存档中查找bean。它忽略其他模块。

现在,你可能想知道我们在这里是否犯了错误。为什么应该以模块为标准来包括/排除一个类。为什么不考虑

  • 类级别的注解,
  • 包,
  • 它实现或扩展的类型,或者
  • 某种命名约定。

嗯,我认为我们已经涵盖了第一个选项。注释一个Bean@Alternative,或者使用替代的元数据,CDI会将其视为禁用,除非你明确在beans.xml中启用它。这并不完全等同于完全排除类进行扫描,但很接近。(一个区别是,可移植的扩展仍然会收到该类的ProcessAnnotatedType事件。)

排除一个包对我来说是有意义的,CDI的将来版本可能会允许你在beans.xml.

通过类型或命名约定排除Bean对我来说一点吸引力都没有。在CDI的世界中,我们使用元数据来识别架构角色。我们不使用标记接口或命名约定。我强烈反对名称影响功能。

我们将在Weld中试验给你一些更细粒度的控制Bean发现的方法。然而,我的预期是当前的解决方案将非常适合大多数人。


返回顶部