CDI 和 EJB 如何比较?互动?

2022-08-31 09:35:39

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

我知道两者都有相关的注释,但我无法找到两者的完整列表以及简要描述。不确定这是否有助于澄清它们之间的差异或重叠的位置。

真的只是困惑。我(认为我)相当了解EJB,我想我很难确切地理解CDI带来了什么,以及它如何取代或增强EJB已经提供的东西。


答案 1

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

CDI是这个街区的新孩子。CDI 豆功能 ,以及 .CDI豆在注射和范围界定方面是最灵活的。事件总线非常轻量级,非常适合最简单的 Web 应用程序。除此之外,CDI还公开了一个非常高级的功能,称为,这是一种插件机制,供供应商为Java EE提供额外的功能,可以在所有实现(Glassfish,JBoss AS,Websphere等)上使用。dependency injectionscopingevent busportable extensions

EJB3 bean 是从旧的 EJB2 组件模型* 中改造而来的,并且是 Java EE 中第一个通过注释管理 Bean 的 Bean。EJB3 bean 功能 、 、 、 、 和 。dependency injectiondeclarative transactionsdeclarative securitypoolingconcurrency controlasynchronous executionremoting

EJB3 bean 中的依赖注入不如 CDI Bean 灵活,EJB3 Bean 没有作用域的概念。但是,EJB3 bean 是事务性的,并且默认是池化的**,这是 CDI 选择在 EJB3 域中保留的两个非常有用的东西。其他提到的项目在 CDI 中也不可用。EJB3没有自己的事件总线,但它确实有一种特殊类型的bean用于收听消息;消息驱动的 Bean。这可用于从 Java 消息传递系统或具有 JCA 资源适配器的任何其他系统接收消息。对简单事件使用完整的消息传递比 CDI 事件总线更重要,EJB3 只定义了一个侦听器,而不是一个生产者 API。

自从 JSF 被包含以来,JSF 管理 Bean 就已经存在于 Java EE 中。它们也具有和 .JSF 托管 Bean 引入了声明性作用域的概念。最初,作用域相当有限,在相同版本的Java EE中,EJB3 Bean已经可以通过注释声明,JSF托管Bean仍然必须用XML声明。当前版本的 JSF 托管 Bean 也最终通过注释进行声明,并且使用视图作用域和创建自定义作用域的功能扩展作用域。视图作用域(记住对一页面的请求之间的数据)是 JSF 托管 Bean 的一项独特功能。dependency injectionscoping

除了视图范围之外,Java EE 6 中的 JSF 托管 Bean 仍然很少。不幸的是,CDI中缺少视图范围,因为否则CDI将是JSF托管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 添加作用域支持。

专家组成员和CDI实现CanDI的实施者Reza Rahman经常暗示,与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 中的模型需要一个重量级且过于冗长的 XML 部署描述符来描述每个 Bean, 此外,还需要bean来实现各种重量级且大部分无意义的组件接口。

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


答案 2

CDI:这是关于依赖注入的。这意味着您可以在任何地方注入接口实现。这个对象可以是任何东西,也可以是与 EJB 无关的对象。以下是如何使用CDI注入随机生成器的示例。没有关于EJB的任何内容。当你想要注入非 EJB 服务、不同的实现或算法时,你将使用 CDI(所以你根本不需要 EJB)。
EJB:你确实理解,并且可能你对注释感到困惑 - 它允许你将实现注入到你的服务中或其他任何东西。主要思想是,注入的类应该由 EJB 容器管理。似乎CDI确实理解EJB是什么,所以在Java EE 6兼容的服务器中,在你的servlet中,你可以同时编写两者。@EJB

@EJB EJBService ejbService;

@Inject EJBService ejbService;

这就是让你感到困惑的原因,但这可能是EJB和CDI之间的唯一桥梁。

当我们谈论CDI时,您可以将其他对象注入CDI托管类(它们应该由CDI感知框架创建)。

CDI还提供什么...例如,您使用 Struts 2 作为 MVC 框架(仅举例),即使使用 EJB 3.1,您也受到限制 - 您不能在 Struts 操作中使用注释,它不受容器管理。但是当你添加Struts2-CDI插件时,你可以为同样的事情写注释(所以不需要更多的JNDI查找)。通过这种方式,它增强了EJB的功能,但正如我之前提到的,你用CDI注入了什么 - 它是否与EJB相关并不重要,这就是它的功能。@EJB@Inject

PS. 更新了示例的链接


推荐