我正在制作一个基于 Java EE 的产品,其中我使用GlassFish 3 和 EJB 3.1。
我的应用程序有会话 bean、调度程序并使用 Web 服务。我最近了解了支持Contexts and Dependency Injection (CDI)的Apache TomEE。GlassFish 容器还支持 CDI。
我可以在不需要 CDI 还没有提供的任何功能的情况下替换会话 bean 吗?如果那样的话,我能得到什么好处?
我正在制作一个基于 Java EE 的产品,其中我使用GlassFish 3 和 EJB 3.1。
我的应用程序有会话 bean、调度程序并使用 Web 服务。我最近了解了支持Contexts and Dependency Injection (CDI)的Apache TomEE。GlassFish 容器还支持 CDI。
我可以在不需要 CDI 还没有提供的任何功能的情况下替换会话 bean 吗?如果那样的话,我能得到什么好处?
是的,您可以自由地混合 CDI 和 EJB 并取得一些很好的结果。听起来您正在使用@WebService
and @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 的类型为 ,容器也会查看 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 bean 也成为 EJB 时,您才可以选择@Stateful
使用@Stateless
它@Singleton
。
以下是我何时分解 EJB 的简短列表。
公开 JAX-WS @WebService
。我很懒。当@WebService
也是 EJB 时,您不必列出它并将其映射为web.xml
文件中的 servlet。这对我来说是工作。另外,我可以选择使用下面提到的任何其他功能。所以这对我来说是理所当然的。
仅@Stateless
适用于@Singleton
。
通过 . 公开 JAX-RS 资源@Path
。我还是很懒。当 RESTful 服务也是 EJB 时,您再次获得自动发现,而不必将其添加到 JAX-RSApplication
子类或类似的东西中。@WebService
另外,如果我想要或使用下面提到的任何强大功能,我可以公开完全相同的 bean 。
仅@Stateless
适用于@Singleton
。
启动时通过 加载@Startup
。目前在 CDI 中没有与此等效的功能。不知何故,我们错过了AfterStartup
在容器生命周期中添加事件之类的东西。如果我们这样做了,你就可以拥有一个@ApplicationScoped
监听它的 bean,它实际上与@Singleton
with相同@Startup
。它在 CDI 1.1 的列表中。
仅适用于@Singleton
。
@Asynchronous
方法调用。在任何服务器端环境中,启动线程都是禁止的。线程过多是严重的性能杀手。此注释允许您并行化您使用容器的线程池所做的事情。这太棒了。
可用于@Stateful
和。@Stateless
@Singleton
@Schedule
orScheduleExpression
基本上是一个 cron 或Quartz
功能。也非常棒。大多数容器只是为此使用 Quartz。然而,大多数人不知道 Java EE 中的调度工作是事务性的!如果您更新数据库然后安排一些工作并且其中一个失败,则两者都会自动清理。如果EntityManager
持久调用失败或刷新有问题,则无需取消计划工作。是的,交易。
仅@Stateless
适用于@Singleton
。
上面关于事务的注意事项当然要求您使用JTA
托管的EntityManager
. UserTransaction
您可以将它们与普通的“CDI”一起使用,但如果没有容器管理的事务,复制提交/回滚逻辑会变得非常单调。
可用于所有 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 和数据库连接就不必作为请求的一部分注入