在哪里使用EJB 3.1和CDI?

Dhr*_*hah 115 cdi ejb-3.0 glassfish-3 apache-tomee

我正在制作一个基于Java EE的产品,我正在使用GlassFish 3和EJB 3.1.

我的应用程序有会话bean,调度程序和使用Web服务.我最近了解了Apache TomEE,它支持上下文和依赖注入(CDI).GlassFish容器也支持CDI.

我可以替换会话bean,我不需要任何CDI也没有提供的功能吗?如果那样的话,我能得到什么好处?

Dav*_*ins 381

是的,您可以自由地混合使用CDI和EJB,并获得一些很好的结果.这听起来像你正在使用@WebService@Schedule,这是很好的理由将EJB的组合.

那里有很多混淆,所以这里有一些关于EJB和CDI的一般信息,因为它们与每个有关.

EJB> = CDI

请注意,EJB CDI bean,因此具有CDI的所有优点.反之亦然(尚未).因此,绝对不要养成思考"EJB vs CDI"的习惯,因为该逻辑实际上转换为"EJB + CDI与CDI",这是一个奇怪的等式.

在Java EE的未来版本中,我们将继续对齐它们.什么整合机构是让人们做他们已经可以做什么,只是没有@Stateful,@Stateless@Singleton在顶部的注释.

实施条款中的EJB和CDI

最终,EJB和CDI共享代理组件的基本设计.当您获得对EJB或CDI bean的引用时,它不是真正的bean.相反,你给出的对象是假的(代理).当您在此假对象上调用方法时,调用将转到将通过拦截器,装饰器等发送调用的容器,以及处理任何事务或安全检查.完成所有操作后,调用最终转到真实对象,结果通过代理传递回调用者.

区别仅在于如何解析要调用的对象.通过"已解决",我们只是指容器在何处以及如何查找要调用的实例.

在CDI中,容器在"范围"中查找,它基本上是一个特定时间段内的哈希映射(每个请求@RequestScoped,每个HTTP会话@SessionScoped,每个应用程序@ApplicationScoped,JSF会话@ConversationScoped或根据您的自定义范围实现).

在EJB中,如果bean是类型,容器也会看到一个hashmap @Stateful.一个@Stateful豆也可以使用任何上述范围注释导致其生活和在范围内的所有其他豆类死亡.在EJB @Stateful中本质上是"任何作用域"bean.该@Stateless基本上是一个实例池-你从池中的一个调用期间获得一个实例.在@Singleton本质上是@ApplicationScoped

所以在基础层面上,你可以用"CDI"bean做一些"EJB"bean.在封面下,很难区分它们.除了如何解析实例之外,所有管道都是相同的.

在进行此代理时,它们在容器将提供的服务方面目前不同,但正如我所说,我们正在Java EE规范级别上进行处理.

表现说明

忽视你可能拥有的任何"轻"或"沉重"的心理图像.这都是营销.它们在大多数情况下具有相同的内部设计.CDI实例解析可能有点复杂,因为它更具动态性和上下文性.相比之下,EJB实例解析相当静态,愚蠢和简单.

我可以从TomEE的实现角度告诉您,调用EJB与调用CDI bean之间的性能差异为零.

默认为POJO,然后是CDI,然后是EJB

当然,如果没有任何好处,请不要使用CDI或EJB.当您开始想要注射,事件,拦截器,装饰器,生命周期跟踪等等时,请投入CDI.那是大部分时间.

除了这些基本知识,有许多有用的容器服务,你只需要使用的选项,如果你让你的CDI豆也通过增加一个EJB @Stateful,@Stateless@Singleton在其上.

这是我打破EJB时的简短列表.

使用JAX-WS

公开JAX-WS @WebService.我很懒.当@WebService它也是EJB时,您不必列出它并将其映射为web.xml文件中的servlet .这对我有用.另外,我可以选择使用下面提到的任何其他功能.所以对我来说这是一个明智的选择.

仅限@Stateless和可用@Singleton.

使用JAX-RS

通过公开JAX-RS资源@Path.我还是很懒.当RESTful服务也是EJB时,您再次获得自动发现,而不必将其添加到JAX-RS Application子类或类似的东西.另外,@WebService如果我想要或使用下面提到的任何强大功能,我可以公开完全相同的bean .

仅限@Stateless和可用@Singleton.

启动逻辑

通过启动加载@Startup.CDI目前没有相同的内容.不知怎的,我们错过了AfterStartup在容器生命周期中添加类似事件的东西.如果我们做到了这一点,你根本可以有一个@ApplicationScoped是听了它,这将有效地一样的豆@Singleton@Startup.它在CDI 1.1的列表中.

仅适用于@Singleton.

并行工作

@Asynchronous方法调用.在任何服务器端环境中启动线程都是禁忌.拥有太多线程是严重的性能杀手.此批注允许您使用容器的线程池并行化您执行的操作.这太棒了.

可用来@Stateful,@Stateless@Singleton.

调度工作

@Schedule或者ScheduleExpression基本上是一个cron或Quartz功能.也很棒.大多数容器只是在封面下使用Quartz.但是,大多数人不知道Java EE中的调度工作是事务性的!如果您更新数据库然后安排一些工作,其中一个失败,它们将自动清理.如果EntityManager持久呼叫失败或刷新有问题,则无需取消安排工作.是的,交易.

仅限@Stateless和可用@Singleton.

在JTA事务中使用EntityManagers

以上关于交易的说明当然要求您使用JTA托管EntityManager.您可以将它们与普通的"CDI"一起使用,但如果没有容器管理的事务,它可能会变得非常单调地复制UserTransaction提交/回滚逻辑.

适用于所有的Java EE组件,包括CDI,JSF @ManagedBean,@WebServlet,@WebListener,@WebFilter,等@TransactionAttribute注释,但是,是提供给@Stateful,@Stateless@Singleton只.

保持JTA管理 EntityManager

EXTENDED管理EntityManager可以让你保持一EntityManager间开放式JTA的交易,而不是失去缓存的数据.适合时间和地点的好功能.负责任地使用:)

仅适用于@Stateful.

轻松同步

当您需要同步时,@Lock(READ)@Lock(WRITE)注释非常好.它允许您免费获得并发访问管理.跳过所有ReentrantReadWriteLock管道.在同一个存储桶中@AccessTimeout,它允许您说明线程在放弃之前应该等待多长时间才能访问bean实例.

仅适用于@Singleton豆类.

  • 天哪大卫:)我想你已经覆盖了它. (26认同)
  • 我非常喜欢这个答案.完美的工作! (12认同)
  • 谢谢你的回答.你已经清除了我头上的堵塞并连接了很多点. (7认同)
  • 到目前为止,这是我读过的那个主题的最佳解释.它还涵盖了实际使用中EJB的几乎所有重要方面.做得好!! (7认同)
  • 这个答案是 2012 年的,我们最近有更新吗? (7认同)
  • 非常可以理解,亚当在严格的法律条款中没有错,但这种区别没有实际意义.规范说EJB实例不是上下文,但后来说EJB的引用(代理)是上下文的.有状态bean的生命周期完全通过引用(代理)来控制,因此当CDI容器控制该引用(代理)时,数学就会变得相同 - 有状态EJB可以有效地成为上下文. (3认同)
  • 你在TESLA的午休时间写过这个吗? (3认同)
  • 还要注意,EJB规范只允许`Stateless`和`Singleton` bean是JAX-RS或JAX-WS Web服务。HTTP会话或JAX-RS或JAX-WS的“有状态” bean的任何使用都是不可移植的。 (2认同)
  • 非常感谢.我无法想象为什么这个答案不在社区维基中. (2认同)
  • 我很乐意给你更多的赞成...很棒的答案:D (2认同)
  • 这可能是一个愚蠢的问题,但是 - EJB 和 CDI 是共享同一个容器还是使用不同的容器? (2认同)