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


106

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

我知道两者都有相关的注释,但是我无法通过简要说明找到两者的完整列表。不知道这是否有助于弄清它们之间的区别或重叠之处。

真的只是糊涂了。我(认为我)相当了解EJB,我想很难确切地了解CDI给表带来了什么,以及它如何取代或增强EJB已经提供的功能。


3
这个问题排在Google的“ EJB CDI差异”搜索的顶部,但我在stackoverflow.com/questions/13487987/…上找到了答案
matt freake 2014年

Answers:


50

CDI:关于依赖注入。这意味着您可以在任何地方注入接口实现。该对象可以是任何东西,可以与EJB不相关。是如何使用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的情况下,也受到了限制-您不能@EJB在Struts操作中使用注释,它不是由容器管理的。但是,当您添加Struts2-CDI插件时,您可以在此处@Inject为同一内容编写注释(因此,无需进行其他JNDI查找)。这样,它可以增强EJB的功能,但是正如我之前提到的,您要使用CDI注入的内容-它与EJB是否相关都没有关系,这就是它的功能。

PS。更新到示例的链接


@EJB和@Inject在功能上是否真正等效?我认为CDI和Java EE的其他首字母缩略词汤之间的注入方法重叠使我感到困惑。更多的阅读似乎表明有希望对齐注释。
蒂姆(Tim)

@Maxym在使用@ Inject时,如何确保@ Stateless或EJB的任何其他服务器端组件仍使用容器提供的诸如Pooling或并发之类的功能。我希望这不是CDI提供的吗?
Bala 2012年

1
@Bala:CDI不提供集中......看看CDI带或不带EJB3.1,希望这回答了您的问题..
Maxym

@KorayTugay:CDI是Java EE的功能,因此任何符合Java EE 6的服务器都具有(Classfish 3.0.1+没错,JBoss 6+等)。您可以查看JBoss Weld,这是您参考的CDI实现例如可以在Tomcat中使用...
Maxym 2014年

191

当前确实确实有些混乱,因为Java EE中现在有多个组件模型。它们是CDIEJB3JSF托管Bean

CDI是新手。CDI豆功能dependency injectionscoping以及event bus。CDI bean在注入和作用域方面最灵活。事件总线非常轻巧,非常适合于最简单的Web应用程序。除此之外,CDI还公开了一个非常高级的功能,称为portable extensions,这是一种插件机制,供供应商向Java EE提供可在所有实现(Glassfish,JBoss AS,Websphere等)上使用的额外功能。 。

EJB3 bean是从旧的遗留EJB2组件模型*改造而来的,并且是Java EE中第一个通过注释进行管理的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以来,Java EE中就已经存在JSF托管Bean。他们也有特色dependency injectionscoping。JSF Managed Beans引入了声明性作用域的概念。最初,范围是相当有限的,并且在已经可以通过注释声明EJB3 bean的同一版本的Java EE中,仍然必须以XML声明JSF受管Bean。最后,还将通过注释声明当前版本的JSF托管Bean,并使用视图范围和创建自定义范围的功能来扩展范围。视图范围可以记住对同一页面的请求之间的数据,这是JSF托管Bean的独特功能。

除了视图范围之外,Java EE 6中的JSF托管Bean几乎没有用。不幸的是,缺少CDI的视图范围是不幸的,因为否则CDI将是JSF托管Bean提供的完美的超级集。更新:在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添加范围支持。

Reza Rahman是CanDI的CDI实现的专家组成员和实现者,他经常暗示与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中的模型则是重量级的,每个bean都需要过于冗长的XML部署描述符,此外还需要bean来实现各种极其重量级的组件,并且在大多数情况下是毫无意义的组​​件接口。

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


3
您对“ EJB3 bean没有作用域的概念”和“ EJB3虽然没有自身的事件总线”的说法感到有些困惑。这与David Blevin的主张“ EJB CDI Bean,因此具有CDI的所有优点” 说法相符吗?在您撰写答案与David撰写Blog条目之间,这方面是否有所改变?
克里斯

5
因为可能有些令人困惑的概念, 实际上并没有真正的“ CDI bean”,但是有一些服务适用于托管bean。为了便于讨论,人们(以及我本人)都将它们称为“ CDI bean”。在CDI之前,EJB bean没有明确的作用域。正如David所解释的,有状态隐式是任何范围(因此特别是没有范围)。有了CDI,EJB bean可以利用CDI提供的范围,没有CDI规范,因此,仅查看EJB规范,就没有明确的范围
Arjan Tijms 2013年

1
您能否详细说明“将服务应用于托管bean”的含义?这是否意味着实际上没有CDI bean这样的东西?仅仅是一些在POJO(EJB)或JSF托管Bean上提供了额外的功能?像能够在JSF托管Bean中使用Inject注释一样?
Koray Tugay 2013年

3
@Chris为了从EJB规范的角度进一步阐明,我们从CDI开始就做出了深思熟虑的决定,要求EJB实现必须支持EJB上100%的CDI功能集。CDI的每个方面都适用于EJB,但范围仅限于状态豆。
David Blevins 2014年

1
注意,JSF 2.2现在提供了javax.faces.view.ViewScoped,这是一个CDI扩展,它实际上是JSF视图范围到CDI的端口。这样,CDI可以完全替代JSF托管Bean。
jdessey 2014年

-1

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

Ejbs和CDI很容易理解。

Ejbs:

  1. 始终由范围限定符注释,例如@ Stateless,@ Stateful,@ Request等
  2. Ejb的实例由Java EE框架控制并进行池化。EE框架的职责是为使用者提供实例。

@Stateless

 public class CarMaker(){
    public void createCar(Specification specs){
        Car car = new Car(specs);
    }
}

CarMaker具有特定的Ejb范围注释,因此,它是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范围注释之间进行更多研究,这将进一步澄清概念。


爱因斯坦还说:“一切都应该尽可能简单,但不要更简单”,您可以(应该)在此处用“解释”替换“制造”。
库克尔特耶
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.