在哪里使用EJB 3.1和CDI?
我正在制作一个基于Java EE的产品,其中使用了GlassFish 3和EJB 3.1。
我的应用程序有会话bean,一个调度程序,并使用Web服务。 我最近才了解Apache TomEE,它支持CDI。 GlassFish容器也支持CDI。
我可以replace会话bean,我不需要任何CDI也没有提供的function吗? 如果那样,我可以得到什么好处?
是的,你可以自由地混合CDI和EJB,并取得一些很好的结果。 这听起来像你正在使用@WebService
和@Schedule
,这是添加EJB的好理由。
这里有很多的困惑,所以这里有一些关于EJB和CDI的一般信息,因为它们相互关联。
EJB> = CDI
请注意,EJB 是 CDI bean,因此具有CDI的所有优点。 相反是不正确的(还)。 所以一定不要养成“EJB vs CDI”这个习惯,因为这个逻辑真正转化为“EJB + CDI vs CDI”,这是一个奇怪的方程。
在未来的Java EE版本中,我们将继续alignment它们。 alignment意味着让人们做他们已经可以做的事情,只是在顶部没有@Stateless
@Stateful
, @Stateless
或者@Singleton
注解。
EJB和CDI的实现条款
最终,EJB和CDI共享代理组件的基本devise。 当你得到一个EJB或CDI bean的引用时,它不是真正的bean。 相反,你给的对象是一个假的(代理)。 当你在这个假对象上调用一个方法时,调用将通过拦截器,装饰器等来发送调用的容器,并处理任何事务或安全检查。 一旦完成,调用终于到达真实对象,结果通过代理传递给调用者。
区别只在于如何parsing被调用的对象。 通过“已解决”,我们只是指容器在何处以及如何查找要调用的实例。
在CDI中,容器在一个“范围”中查找,它基本上是一个在特定时间段内存在的hashmap(每个请求@RequestScoped
,每个HTTP Session @SessionScoped
,每个应用@SessionScoped
ApplicationScoped,JSF Conversation @ConversationScoped
或者每个自定义范围实现)。
在EJB中,如果bean的types是@Stateful
,容器也会查看一个@Stateful
。 一个@Stateful
bean也可以使用上面的任何一个作用域注释,使它和其他所有的bean一起生存和死亡。 在EJB @Stateful
本质上是“任何作用域”的bean。 @Stateless
基本上是一个实例池 – 在一次调用期间,您从池中获取一个实例。 @Singleton
本质上是@ApplicationScoped
所以在基本层面上,任何你可以用“EJB”bean做的事情,你都应该可以用“CDI”bean来做。 在封面之下很难区分他们。 除了实例如何解决之外,所有的pipe道都是一样的。
在进行代理时,它们在容器提供的服务方面目前并不相同,但正如我所说的,我们正在Java EE规范级别上进行这项工作。
性能说明
无视你可能拥有的任何“轻微”或“沉重”的心理影像。 这就是全部营销。 他们大部分都具有相同的内部devise。 CDI实例parsing可能稍微复杂一些,因为它稍微更具dynamic性和上下文性。 EJB实例parsing相当静态,比较愚蠢和简单。
我可以从TomEE的实现angular度告诉你,调用EJB和调用CDI bean之间的性能差别几乎是零。
默认为POJO,然后是CDI,然后是EJB
当然没有好处的时候不要使用CDI或者EJB。 当你开始想要注入,事件,拦截器,装饰器,生命周期跟踪和类似的事情时,抛出CDI。 这是最多的时间。
除了这些基础知识之外,还有一些有用的容器服务,如果您通过在其上添加@Stateless
@Stateful
, @Stateless
或@Singleton
将您的CDI bean也变为EJB,则您只能使用该选项。
以下是我分解EJB时的一个简短列表。
使用JAX-WS
公开JAX-WS @WebService
。 我很懒。 当@WebService
也是一个EJB时,您不必将其列出并将其作为servlet映射到web.xml
文件中。 这对我有用。 另外我可以select使用下面提到的任何其他function。 所以这对我来说是一件容易的事。
仅适用于@Stateless
和@Singleton
。
使用JAX-RS
通过@Path
暴露JAX-RS资源。 我还很懒。 当REST风格的服务也是EJB的时候,你也可以自动发现,而不必把它添加到JAX-RS Application
子类或类似的东西中。 另外,如果我想要或者使用下面提到的任何一个很好的function,我可以公开一个完全相同的bean作为@WebService
。
仅适用于@Stateless
和@Singleton
。
启动逻辑
在启动时通过@Startup
加载。 在CDI中目前还没有这个相同的东西。 不知何故,我们错过了在容器生命周期中添加类似AfterStartup
事件的东西。 如果我们完成了这个任务,你可能只需要一个@ApplicationScoped
bean来监听它,这将和@Startup
的@Singleton
实际上是一样的。 它在CDI 1.1的名单上。
仅适用于@Singleton
。
并行工作
@Asynchronous
方法调用。 在任何服务器端环境中,启动线程都是不允许的。 有太多的线程是一个严重的性能杀手。 这个注解允许你使用容器的线程池来并行化你所做的事情。 这太棒了。
可用于@Stateless
@Stateful
, @Stateless
和@Singleton
。
调度工作
@Schedule
或ScheduleExpression
基本上是一个cron或Quartz
function。 也非常棒。 为了这个,大多数容器只是使用Quartz。 然而,大多数人不知道Java EE中的调度工作是事务性的! 如果您更新数据库,然后安排一些工作,其中一个失败,两者都会自动清理。 如果EntityManager
持续调用失败或者存在EntityManager
问题,则不需要取消调度工作。 耶,交易。
仅适用于@Stateless
和@Singleton
。
在JTA事务中使用EntityManagers
上面关于交易的注释当然要求你使用JTA
pipe理的EntityManager
。 你可以用简单的“CDI”来使用它们,但是如果没有容器pipe理的事务,它可能会非常单调地复制UserTransaction
提交/回滚逻辑。
可用于所有Java EE组件,包括CDI,JSF @Stateless
@Stateful
, @Stateless
@Stateful
, @Stateless
@Stateful
, @Stateless
@WebListener
等。但@TransactionAttribute
注释仅可用于@Stateless
@Stateful
, @Stateless
和@Singleton
。
保持JTApipe理EntityManager
EXTENDED
托pipe的EntityManager
允许您保持一个EntityManager
在JTA
事务之间打开,而不会丢失caching的数据。 良好的function适合的时间和地点。 使用负责任的:)
仅适用于@Stateful
。
易于同步
当你需要同步时, @Lock(READ)
和@Lock(WRITE)
注释非常好。 它允许您免费获得并发访问pipe理。 跳过所有的ReentrantReadWriteLockpipe道。 在同一个桶里有@AccessTimeout
,它允许你说一个线程在放弃之前应该等待多久才能访问bean实例。
仅适用于@Singleton
bean。
如果你真的没有使用ejb 3.1的任何function,答案很简单。 但猜猜你的问题表明你怀疑有ejb 3.1的概念没有意识到他们从中受益。 一个例子可能是容器可以保留一个slsb池准备好使用,所以jms和数据库连接不必注入请求的一部分