问题

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

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

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


#1 热门回答(184 赞)

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

CDI是街区的新生儿。 CDI bean功能dependency injection,scoping和anevent bus。 CDI bean在注射和范围方面是最灵活的。事件总线非常轻巧,非常适合即使是最简单的Web应用程序。除此之外,CDI还公开了一个非常高级的功能,称为portable extensions,这是供应商为Java EE提供额外功能的一种插件机制,可以在所有实现(Glassfish,JBoss AS,Websphere等)上使用。 。

EJB3beans是从旧的遗留EJB2组件模型*进行改进的,并且是Java EE中第一个通过注释成为托管bean的bean。 EJB3 bean功能dependency injection,declarative transactions,declarative security,pooling,concurrency control,asynchronous 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 injection和5667673204。 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中添加了aCDI compatible @ViewScoped,使得CDI确实是完美的超级集.更新2:在JSF2.3中,不推荐使用JSF托管bean来支持CDI托管bean。

使用EJB3和CDI,情况并非如此明确。 EJB3组件模型和API提供了许多CDI不提供的服务,因此通常不能用CDI替换EJB3。另一方面,CDI可以与EJB3结合使用 - 例如向EJB添加范围支持。

专注于CanDI的CDI实现的专家组成员和实现者Reza Rahman经常暗示,与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规范不以任何方式强制它。


#2 热门回答(46 赞)

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


#3 热门回答(-1 赞)

爱因斯坦: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框架管理,实例必须由你自己创建。
  • 它始终是依赖的。让我用例子解释"Dependent":class Specification {private String color;私有字符串模型; // - Getter和Setter}

Specificationclass是CDI,因为它没有用Ejb范围注释,而且这必须由你的代码而不是EE框架初始化。这里要注意的一点是,由于我们没有注释Specificationclass,因此它默认注释为@Dependentannotation。

@Dependent  <- By default added 
class Specification { ... }

Further reading:你需要在Ejbs范围注释和CDI范围注释之间进行更多研究,这将进一步明确概念


原文链接