【问题标题】:How do CDI and EJB compare? interact?CDI 和 EJB 如何比较?相互作用?
【发布时间】:2011-06-08 17:16:19
【问题描述】:

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

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

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

【问题讨论】:

标签: java ejb java-ee-6 cdi


【解决方案1】:

目前确实有点令人困惑,因为现在 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 Managed Beans 自从 JSF 被包含在 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 compatible @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, when to break out the EJBs

* 尽管它只是版本号的增加,但 EJB3 bean 在很大程度上是一种完全不同的 bean:一个简单的 pojo,通过应用一个简单的单个注解变成一个“托管 bean”,而 EJB2 中的模型是一个重量级和过度的每个 bean 都需要详细的 XML 部署描述符,此外还需要 bean 实现各种极其重量级且大部分无意义的组​​件接口。

** 无状态会话 bean 通常是池化的,有状态会话 bean 通常不是(但它们可以是)。因此,对于这两种类型,池都是可选的,EJB 规范并没有强制要求。

【讨论】:

  • 我对您关于“EJB3 bean 没有范围概念”和“EJB3 没有自己的事件总线”的说法感到有些困惑。这与David Blevin's 声称“EJB 是 CDI bean 并因此具有CDI 的所有好处”的说法有何不同?从您写答案到 David 写博客条目时,这方面有什么变化吗?
  • 这是因为可能有点令人困惑的概念,实际上并不是真正的“CDI bean”,但有一些服务应用于托管 bean。为了便于讨论,人们(以及我自己)无论如何都将它们称为“CDI bean”。在 CDI 之前,EJB bean 没有明确的范围。正如 David 解释的那样,Stateful 是隐含的任何范围(因此没有特别的范围)。现在在 CDI 可用的情况下,EJB bean 可以利用 CDI 提供的范围。没有 CDI 规范,因此仅查看 EJB 规范时,没有明确的范围。
  • 您能否详细说明“有服务应用于托管 bean”是什么意思?这是否意味着实际上没有 CDI bean 这样的东西?它只是在 POJO - EJB - 或 JSF Managed Bean 上提供一些额外功能?就像能够在 JSF 托管 Bean 中使用注入注解一样?
  • @Chris 从 EJB 规范的角度进一步澄清,我们从 CDI 开始就做出深思熟虑的决定,要求 EJB 实现必须支持 EJB 上 100% 的 CDI 功能集。 CDI 的每个方面都适用于 EJB,但我们必须仅限于有状态 bean 的范围除外。
  • 请注意,JSF 2.2 现在提供 javax.faces.view.ViewScoped,这是一个 CDI 扩展,它本质上是 JSF 视图范围到 CDI 的一个端口。有了这个,CDI 就完全替代了 JSF Managed Beans。
【解决方案2】:

CDI:它是关于依赖注入的。这意味着您可以在任何地方注入接口实现。这个对象可以是任何东西,它可以与 EJB 无关。 Here 是如何使用 CDI 注入随机生成器的示例。没有关于 EJB 的内容。当您想要注入非 EJB 服务、不同的实现或算法(因此您根本不需要 EJB)时,您将使用 CDI。
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 - 您不能在 Struts 操作中使用 @EJB 注释,它不受容器管理。但是当您添加 Struts2-CDI 插件时,您可以在其中为同一事物编写 @Inject 注释(因此不再需要 JNDI 查找)。这种方式增强了 EJB 的能力,但正如我之前提到的,你用 CDI 注入的东西——它是否与 EJB 相关并不重要,这就是它的能力。

附言。更新示例链接

【讨论】:

  • @EJB 和@Inject 在功能上真的等效吗?我认为是 CDI 和 Java EE 首字母缩略词的其他部分之间的注入方法重叠让我感到困惑。更多的阅读似乎表明有希望对齐注释。
  • @Maxym 当您使用@Inject 时,如何确保@Stateless 或EJB 的任何其他服务器端组件仍然使用容器提供的池或并发等特性。我希望这不是 CDI 提供的,对吧?
  • @Bala:CDI 不提供池...看看CDI with or without EJB3.1,希望它能回答您的问题..
  • @KorayTugay:CDI 是 Java EE 特性,所以任何符合 Java EE 6 的服务器都有(Glassfish 3.0.1+ 没有记错,JBoss 6+ 等)你可以看看 JBoss Weld,一个参考 CDI 实现,您可以在例如 Tomcat 中使用它...
【解决方案3】:

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

Ejbs 和 CDI 很容易理解。

Ejb:

  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作用域注解之间需要进一步研究,这将进一步理清概念

【讨论】:

  • 爱因斯坦还说过:“一切都应该尽可能简单,但不能更简单”您可以(应该)在此处将“制造”替换为“解释”。跨度>
猜你喜欢
  • 2015-08-08
  • 1970-01-01
  • 1970-01-01
  • 2018-02-21
  • 2021-12-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-01
相关资源
最近更新 更多