109

我很难理解两者如何相互作用以及它们之间的界限在哪里。它们重叠吗?他们之间有冗余吗?

我知道两者都有相关的注释,但我无法找到两者的完整列表以及简要说明。不确定这是否有助于弄清楚它们的不同之处或重叠之处。

真的只是一头雾水。我(认为我)对 EJB 的理解相当不错,我想我很难准确理解 CDI 带来了什么以及它如何取代或增强 EJB 已经提供的功能。

4

3 回答 3

195

目前确实有点令人困惑,因为现在 Java EE 中有多个组件模型。它们是CDIEJB3JSF 托管 Bean

CDI是新来的。CDI bean 功能dependency injectionscoping一个event bus. CDI bean 在注入和作用域方面是最灵活的。事件总线非常轻量级,非常适合最简单的 Web 应用程序。除此之外,CDI 还公开了一个非常高级的特性portable extensions,它是一种插件机制,供供应商为 Java EE 提供额外的功能,可以在所有实现(Glassfish、JBoss AS、Websphere 等)上使用.

EJB3 bean 是从旧的遗留 EJB2 组件模型*改造而来的,并且是 Java EE 中第一个通过注释管理 bean 的 bean。EJB3 bean 具有dependency injectiondeclarative transactionsdeclarative securitypoolingconcurrency control和.asynchronous executionremoting

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 injectionscoping. 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 规范并没有强制要求。

于 2011-01-16T14:21:47.600 回答
51

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。更新示例的链接

于 2011-01-13T19:25:42.280 回答
-1

艾尔伯特爱因斯坦:If you can't explain it simply, you don't understand it well enough

Ejbs 和 CDI 很容易理解。

Ejbs:

  1. 将始终由范围限定符注解,例如,@Stateless、@Stateful、@Request 等
  2. Ejbs 的实例由 Java EE 框架控制并汇集。为消费者提供实例是 EE 框架的职责。

@Stateless

 public class CarMaker(){
    public void createCar(Specification specs){
        Car car = new Car(specs);
    }
}

CarMaker 使用特定的 Ejbs 范围进行注释,因此,它是 Ejb

CDI:

  1. 不完全由 EE 框架管理,必须自己创建实例。
  2. 它总是依赖的。让我用例子来解释“依赖”:

    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 范围注释之间进行更多研究,这将进一步明确概念

于 2018-08-09T01:28:39.243 回答