我很难理解两者如何相互作用以及它们之间的界限在哪里。它们重叠吗?他们之间有冗余吗?
我知道两者都有相关的注释,但我无法找到两者的完整列表以及简要说明。不确定这是否有助于弄清楚它们的不同之处或重叠之处。
真的只是一头雾水。我(认为我)对 EJB 的理解相当不错,我想我很难准确理解 CDI 带来了什么以及它如何取代或增强 EJB 已经提供的功能。
目前确实有点令人困惑,因为现在 Java EE 中有多个组件模型。它们是CDI、EJB3和JSF 托管 Bean。
CDI是新来的。CDI bean 功能dependency injection
和scoping
一个event bus
. CDI bean 在注入和作用域方面是最灵活的。事件总线非常轻量级,非常适合最简单的 Web 应用程序。除此之外,CDI 还公开了一个非常高级的特性portable extensions
,它是一种插件机制,供供应商为 Java EE 提供额外的功能,可以在所有实现(Glassfish、JBoss AS、Websphere 等)上使用.
EJB3 bean 是从旧的遗留 EJB2 组件模型*改造而来的,并且是 Java EE 中第一个通过注释管理 bean 的 bean。EJB3 bean 具有dependency injection
、declarative transactions
、 declarative security
、pooling
、concurrency control
和.asynchronous execution
remoting
EJB3 bean 中的依赖注入不如 CDI bean 灵活,而且 EJB3 bean 没有范围的概念。然而,默认情况下,EJB3 bean 是事务性的和池化的**,这是 CDI 选择留在 EJB3 域中的两个非常有用的东西。其他提到的项目在 CDI 中也没有。虽然 EJB3 没有自己的事件总线,但它确实有一种特殊类型的 bean 用于侦听消息;消息驱动的bean。这可用于从 Java 消息传递系统或任何其他具有 JCA 资源适配器的系统接收消息。对简单事件使用完整的消息传递比 CDI 事件总线要重得多,而且 EJB3 只定义了一个侦听器,而不是生产者 API。
自从 JSF 被包含在内以来,JSF Managed Beans就一直存在于 Java EE 中。它们也具有dependency injection
和scoping
. JSF Managed Beans 引入了声明性作用域的概念。最初,范围相当有限,并且在相同版本的 Java EE 中,EJB3 bean 已经可以通过注释声明,JSF 托管 Bean 仍然必须在 XML 中声明。当前版本的 JSF Managed Beans 最终也是通过注释声明的,并且范围通过视图范围和创建自定义范围的能力进行了扩展。视图范围,它记住对同一页面的请求之间的数据是 JSF Managed Beans 的一个独特功能。
除了视图范围之外,Java EE 6 中的 JSF Managed Beans 几乎没有什么进展。不幸的是,CDI 中缺少视图范围,否则 CDI 将成为 JSF Managed Beans 提供的完美超级集。更新:在 Java EE 7/JSF 2.2 中添加了与CDI 兼容的 @ViewScoped,使得 CDI 确实是完美的超级集。更新 2:在 JSF2.3 中,JSF 托管 bean 已被弃用,取而代之的是 CDI 托管 bean。
对于 EJB3 和 CDI,情况并不那么明确。EJB3 组件模型和 API 提供了许多 CDI 不提供的服务,因此通常 EJB3 不能被 CDI 替代。另一方面,CDI 可以与 EJB3 结合使用——例如,为 EJB 添加范围支持。
Reza Rahman,一个名为 CanDI 的 CDI 实现的专家组成员和实现者,经常暗示与 EJB3 组件模型相关的服务可以作为一组 CDI 注释进行改造。如果发生这种情况,Java EE 中的所有托管 bean 都可能成为 CDI bean。这并不意味着 EJB3 消失或过时,只是它的功能将通过 CDI 而非 EJB 自己的注释(如 @Stateless 和 @EJB)公开。
更新
TomEE 和 OpenEJB 成名的 David Blevins 在他的博客中很好地解释了 CDI 和 EJB 之间的异同:CDI,何时打破 EJB
* 虽然它只是版本号的增加,但 EJB3 bean 在很大程度上是一种完全不同的 bean:一个简单的 pojo,通过应用一个简单的单个注释变成一个“托管 bean”,而 EJB2 中的模型是一个重量级和每个 bean 都需要过于冗长的 XML 部署描述符,此外还需要 bean 来实现各种极其重量级且大部分无意义的组件接口。
** 无状态会话 bean 通常是池化的,有状态会话 bean 通常不是(但它们可以是)。因此,对于这两种类型,池都是可选的,EJB 规范并没有强制要求。
CDI:它是关于依赖注入的。这意味着您可以在任何地方注入接口实现。这个对象可以是任何东西,它可以与 EJB 无关。这是一个如何使用 CDI 注入随机生成器的示例。没有关于 EJB 的内容。当您想要注入非 EJB 服务、不同的实现或算法时,您将使用 CDI(因此您根本不需要 EJB)。
EJB:您确实理解,并且可能您对@EJB
注释感到困惑-它允许您将实现注入您的服务或其他任何东西。主要思想是注入的类应该由 EJB 容器管理。似乎 CDI 确实了解 EJB 是什么,因此在符合 Java EE 6 的服务器中,在您的 servlet 中您可以同时编写
@EJB EJBService ejbService;
和
@Inject EJBService ejbService;
这可能会让您感到困惑,但这可能是 EJB 和 CDI 之间唯一的桥梁。
当我们谈论 CDI 时,您可以将其他对象注入 CDI 托管类(它们应该由 CDI 感知框架创建)。
CDI 还提供什么... 例如,您使用 Struts 2 作为 MVC 框架(只是示例),并且您在此受到限制,即使使用 EJB 3.1 - 您不能@EJB
在 Struts 操作中使用注释,它不是由容器管理的。但是当您添加 Struts2-CDI 插件时,您可以@Inject
为同一事物编写注释(因此不再需要 JNDI 查找)。这种方式增强了 EJB 的能力,但正如我之前提到的,你用 CDI 注入的东西——它是否与 EJB 相关并不重要,这就是它的能力。
PS。更新示例的链接
艾尔伯特爱因斯坦:If you can't explain it simply, you don't understand it well enough
Ejbs 和 CDI 很容易理解。
Ejbs:
@Stateless
public class CarMaker(){
public void createCar(Specification specs){
Car car = new Car(specs);
}
}
CarMaker 使用特定的 Ejbs 范围进行注释,因此,它是 Ejb
CDI:
它总是依赖的。让我用例子来解释“依赖”:
class Specification {
private String color;
private String model;
//- Getter and Setter
}
该类Specification
是 CDI,因为它没有用 Ejb 范围注释,而且它必须由您的代码而不是 EE 框架初始化。这里需要注意的一点是,由于我们没有对Specification
类进行注解,所以默认是通过注解来@Dependent
注解的。
@Dependent <- By default added
class Specification { ... }
Further reading:
您需要在 Ejbs 范围注释和 CDI 范围注释之间进行更多研究,这将进一步明确概念