在哪里使用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

调度工作

@ScheduleScheduleExpression基本上是一个cron或Quartzfunction。 也非常棒。 为了这个,大多数容器只是使用Quartz。 然而,大多数人不知道Java EE中的调度工作是事务性的! 如果您更新数据库,然后安排一些工作,其中一个失败,两者都会自动清理。 如果EntityManager持续调用失败或者存在EntityManager问题,则不需要取消调度工作。 耶,交易。

仅适用于@Stateless@Singleton

在JTA事务中使用EntityManagers

上面关于交易的注释当然要求你使用JTApipe理的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允许您保持一个EntityManagerJTA事务之间打开,而不会丢失caching的数据。 良好的function适合的时间和地点。 使用负责任的:)

仅适用于@Stateful

易于同步

当你需要同步时, @Lock(READ)@Lock(WRITE)注释非常好。 它允许您免费获得并发访问pipe理。 跳过所有的ReentrantReadWriteLockpipe道。 在同一个桶里有@AccessTimeout ,它允许你说一个线程在放弃之前应该等待多久才能访问bean实例。

仅适用于@Singleton bean。

如果你真的没有使用ejb 3.1的任何function,答案很简单。 但猜猜你的问题表明你怀疑有ejb 3.1的概念没有意识到他们从中受益。 一个例子可能是容器可以保留一个slsb池准备好使用,所以jms和数据库连接不必注入请求的一部分

Interesting Posts