我正在制作基于Java EE的产品,其中使用了GlassFish 3和EJB 3.1。
我的应用程序具有会话bean,调度程序并使用Web服务。最近,我开始了解Apache TomEE,它支持上下文和依赖注入(CDI)。GlassFish容器还支持CDI。
我可以在不需要CDI尚未提供的任何功能的情况下替换会话bean吗?如果那样的话,我可以获得什么好处?
我正在制作基于Java EE的产品,其中使用了GlassFish 3和EJB 3.1。
我的应用程序具有会话bean,调度程序并使用Web服务。最近,我开始了解Apache TomEE,它支持上下文和依赖注入(CDI)。GlassFish容器还支持CDI。
我可以在不需要CDI尚未提供的任何功能的情况下替换会话bean吗?如果那样的话,我可以获得什么好处?
Answers:
是的,您可以自由地混合使用CDI和EJB并获得一些不错的结果。听起来您正在使用@WebService
和@Schedule
,这是将EJB添加到组合中的充分理由。
那里有很多混乱,因此这里是有关EJB和CDI的一些常规信息,因为它们彼此相关。
请注意,EJB 是 CDI Bean,因此具有CDI的所有优点。反之亦然(尚未)。因此,绝对不要养成思考“ EJB vs CDI”的习惯,因为该逻辑实际上转化为“ EJB + CDI vs CDI”,这是一个奇怪的方程式。
在将来的Java EE版本中,我们将继续调整它们。什么调整装置是让人们做他们已经可以做什么,只是没有@Stateful
,@Stateless
或@Singleton
在顶部的注释。
最终,EJB和CDI共享被代理组件的相同基本设计。当您获得对EJB或CDI bean的引用时,它不是真正的bean。而是给您的对象是伪造的(代理)。当您在该假对象上调用方法时,调用将转到容器,该容器将通过拦截器,装饰器等将调用发送给该容器,并负责所有事务或安全检查。完成所有操作后,调用将最终转到真实对象,结果通过代理传递回调用者。
区别仅在于如何解决要调用的对象。所谓“已解决”,我们仅表示容器在何处以及如何查找要调用的实际实例。
在CDI中,容器看起来是一个“作用域”,基本上是一个存在特定时间段(每个请求@RequestScoped
,每个HTTP会话@SessionScoped
,每个应用程序@ApplicationScoped
,JSF会话@ConversationScoped
或您的自定义范围实现)的哈希图。
在EJB中,如果bean是type,则容器还会查找一个hashmap @Stateful
。一个@Stateful
bean也可以使用上述范围注释中的任何一个,使其与该范围中的所有其他bean一起生存和死亡。在EJB @Stateful
中,本质上是“任何范围的” bean。该@Stateless
基本上是一个实例池-你从池中的一个调用期间获得一个实例。在@Singleton
本质上是@ApplicationScoped
因此,从根本上讲,使用“ EJB” Bean可以执行的任何操作都应该可以使用“ CDI” Bean进行。在幕后很难将它们区分开。除了解决实例的方式外,所有管道均相同。
就容器在执行此代理时将提供的服务而言,当前它们并不相同,但是正如我所说的,我们正在Java EE规范级别上对其进行研究。
忽略您可能拥有的任何“轻”或“沉重”的心理图像。这就是营销。它们大部分具有相同的内部设计。CDI实例解析可能稍微复杂一点,因为它更具动态性和上下文相关性。相比之下,EJB实例解析是相当静态的,愚蠢的和简单的。
我可以从TomEE的实现角度告诉您,调用EJB与调用CDI bean之间的性能差异大约为零。
当然,在没有好处的情况下不要使用CDI或EJB。当您开始需要注入,事件,拦截器,装饰器,生命周期跟踪之类的东西时,请使用CDI。多数时间。
除了这些基本知识,有许多有用的容器服务,你只需要使用的选项,如果你让你的CDI豆也通过增加一个EJB @Stateful
,@Stateless
或@Singleton
在其上。
这是我分解EJB的简短列表。
公开一个JAX-WS @WebService
。我很懒。当@WebService
也是EJB时,您不必列出它并将其映射为web.xml
文件中的servlet 。那对我有用。另外,我还可以选择使用下面提到的任何其他功能。所以对我来说,这很容易。
仅适用于@Stateless
和@Singleton
。
通过公开一个JAX-RS资源@Path
。我还是很懒。当RESTful服务也是EJB时,您将再次获得自动发现,而不必将其添加到JAX-RS Application
子类或类似的东西。另外,@WebService
如果我想要或使用下面提到的任何出色功能,我都可以公开与之完全相同的bean 。
仅适用于@Stateless
和@Singleton
。
通过启动加载@Startup
。CDI中目前没有与此等效的功能。不知何故,我们错过了AfterStartup
在容器生命周期中添加类似事件的内容。完成此操作后,您可能只拥有一个@ApplicationScoped
侦听它的bean,并且实际上@Singleton
与with 相同@Startup
。它在CDI 1.1列表中。
仅适用于@Singleton
。
@Asynchronous
方法调用。在任何服务器端环境中启动线程都是禁忌。线程太多是严重的性能杀手。该注释使您可以并行化使用容器的线程池执行的操作。这太棒了。
可用来@Stateful
,@Stateless
和@Singleton
。
@Schedule
或者ScheduleExpression
基本上是cron或Quartz
功能。也很棒。大多数容器只是在盖子下使用Quartz。但是,大多数人不知道Java EE中的调度工作是事务性的!如果更新数据库,然后安排一些工作,但其中一项失败,则两者都会自动清理。如果EntityManager
持久调用失败或刷新有问题,则无需取消计划工作。是的,交易。
仅适用于@Stateless
和@Singleton
。
上面有关交易的注释当然要求您使用JTA
托管EntityManager
。您可以将它们与普通的“ CDI”一起使用,但是如果没有容器管理的事务,复制UserTransaction
提交/回滚逻辑可能会变得非常单调。
适用于所有的Java EE组件,包括CDI,JSF @ManagedBean
,@WebServlet
,@WebListener
,@WebFilter
,等@TransactionAttribute
注释,但是,是提供给@Stateful
,@Stateless
并@Singleton
只。
EntityManager
该EXTENDED
管理EntityManager
可以让你保持一EntityManager
间开放式JTA
的交易,而不是丢失缓存数据。在正确的时间和地点提供好的功能。负责任地使用:)
仅适用于@Stateful
。
当您需要同步时,@Lock(READ)
和@Lock(WRITE)
注释非常出色。它使您可以免费获取并发访问管理。跳过所有的ReentrantReadWriteLock管道。在相同的存储桶中@AccessTimeout
,您可以说一个线程在放弃之前应该等待多长时间才能访问bean实例。
仅适用于@Singleton
豆类。
如果您确实没有使用ejb 3.1的任何功能,那么答案很简单。但是猜想您的提问表明您怀疑有ejb 3.1概念正在从中受益,而没有意识到它们。一个示例可能是容器可以准备使用slsb池,因此jms和数据库连接不必作为请求的一部分插入