CDI和EJB如何比较?相互作用?

时间:2011-01-13 19:03:35

标签: java ejb java-ee-6 cdi

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

我知道有两个注释都有关联,但我无法通过简短的描述找到两者的完整列表。不确定这是否有助于澄清它们之间的区别或重叠的位置。

真的很困惑。我(我认为)合理地理解EJB,我想我很难理解CDI带来的确切内容以及它如何取代或增强EJB已经提供的内容。

3 个答案:

答案 0 :(得分:186)

目前确实有点令人困惑,因为Java EE中现在有多个组件模型。它们是 CDI EJB3 JSF Managed Beans

CDI 是该街区的新生儿。 CDI bean功能dependency injectionscopingevent 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 controlasynchronous executionremoting

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

自从包含JSF以来,

JSF Managed Beans 一直存在于Java EE中。它们也有dependency injectionscoping。 JSF Managed Beans引入了声明性范围的概念。最初的范围相当有限,并且在相同版本的Java EE中,EJB3 bean已经可以通过注释声明,JSF Managed Beans仍然必须以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不提供的服务,因此通常不能用CDI替换EJB3。另一方面,CDI可以与EJB3结合使用 - 例如为EJB添加范围支持。

专业组成员和CDI实现的实施者Reza Rahman称为CanDI,他经常暗示与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:通过应用简单的单个注释成为“托管bean”的简单pojo,而EJB2中的模型则是重量级和过度的每个bean都需要详细的XML部署描述符,除了实现各种非常重量级和大多数无意义的组​​件接口所需的bean之外。

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

答案 1 :(得分:47)

CDI - 它是关于依赖注入的。这意味着您可以在任何地方注入接口实现。这个对象可以是任何东西,它可以与EJB无关。 Here是如何使用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 - 你不能在Struts动作中使用@EJB注释,它是不是由容器管理。但是当你添加Struts2-CDI插件时,你可以在那里写@Inject注释同样的东西(因此不需要更多的JNDI查找)。这样可以增强EJB的功能。但正如我之前提到的,你用CDI注入了什么 - 它与EJB是否相关并不重要,这就是它的力量

PS。更新了示例

的链接

答案 2 :(得分:-1)

爱因斯坦(Albert Einstein):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范围注释之间进行更多研究,这将进一步澄清概念