CDI 和 EJB 如何比较?相互作用?
Posted
技术标签:
【中文标题】CDI 和 EJB 如何比较?相互作用?【英文标题】:How do CDI and EJB compare? interact? 【发布时间】:2011-06-08 17:16:19 【问题描述】:我很难理解这两者如何相互作用以及它们之间的界限在哪里。它们重叠吗?它们之间有冗余吗?
我知道两者都有相关的注释,但我无法找到两者的完整列表以及简要说明。不确定这是否有助于弄清楚它们的不同之处或重叠之处。
真的很困惑。我(认为我)对 EJB 的理解相当不错,我想我很难准确理解 CDI 带来了什么以及它如何取代或增强 EJB 已经提供的功能。
【问题讨论】:
这个问题在 Google 的“EJB CDI 差异”搜索中排在首位,但我在 ***.com/questions/13487987/…clearer 找到了答案 【参考方案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:
-
将始终由范围限定符注解,例如,@Stateless、@Stateful、@Request 等
Ejbs 的实例由 Java EE 框架控制并汇集。为消费者提供实例是 EE 框架的职责。
@Stateless
public class CarMaker()
public void createCar(Specification specs)
Car car = new Car(specs);
CarMaker 使用特定的 Ejbs 范围注解,因此,它是 Ejb
CDI:
-
不完全由 EE 框架管理,必须自己创建实例。
它总是依赖的。让我用例子来解释“依赖”:
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作用域注解之间需要进一步研究,这将进一步理清概念
【讨论】:
爱因斯坦还说过:“一切都应该尽可能简单,但不能更简单”您可以(应该)在此处将“制造”替换为“解释”。跨度>以上是关于CDI 和 EJB 如何比较?相互作用?的主要内容,如果未能解决你的问题,请参考以下文章
在较新版本的 JSF 中,@FacesValidator 和 @FacesConverter 中的 EJB 和 CDI 注入点无法通过 OmniFaces 工作