12

我们都知道,在 Web 层中,可能只存在给定 Servlet 的单个实例,它服务于多个请求。这可能会导致实例变量中的线程问题。

我的问题是,使用 @EJB 注释将 EJB 作为实例变量注入 servlet 是否安全?

我最初的直觉是不会,假设同一个 EJB 实例会同时服务多个请求。这似乎也是许多其他程序员的本能:不要注入到 servlet

但是,我是否跳到了错误的结论。很明显,注入到 servlet 的是代理,在底层,容器实际上是否使用不同的实例为每个请求提供服务并维护线程安全?正如这个论坛所建议的那样:Do inject to servlet

似乎有很多相互矛盾的意见。哪个是对的???

4

4 回答 4

11

只要 EJB 是无状态的,将 EJB 作为 Servlet 实例变量注入 Servlet 是安全的。你绝不能在 Servlet 中注入有状态的 Bean。

您必须实现 EJB 无状态,因为它不包含任何本身包含有状态值的实例变量(如持久性上下文)。如果需要使用持久化上下文,则必须在 EJB 的方法中获取它的实例。您可以通过将 PersistenceContextFactory 作为 EJB 实例变量来做到这一点,然后在 EJB 的方法中从工厂获取实体管理器的实例。

PersistenceContextFactory 是线程安全的,因此可以将其注入实例变量中。

只要遵守上述规则,在 Servlet 中注入 Stateless Bean 应该是线程安全的

于 2009-03-25T15:36:25.863 回答
3

您的参考“不要注入到 servlet”没有提及 ejbs 或 @ejb 注释。它讨论了非线程安全的对象,例如 PersistenceContext。

根据 EJB 规范,您可以从各种远程客户端访问 ejb,包括 servlet(EJB 3.0 规范 (JSR-220) - 第 3.1 节)。使用@EJB 注解注入 ejb 是一种通过依赖注入(第 3.4.1 节)获取 EJB 接口的方法,它可以替代在 JNDI 命名空间中查找 ejb 对象。因此,对于获得的 EJB,@EJB 注释没有什么特别之处。

因此,基于 EJB 3.0 规范,使用 @EJB 注释从 servlet 获取 ejb 是一种标准做法。

于 2009-03-07T04:21:01.957 回答
1

这是一个混合包。

无状态会话 bean 可以被注入并且是安全的。这是因为即使使用存根的单个实例,对方法的访问也将由容器序列化。

我认为 inferreddesign 所说的不是真的。无状态会话 bean 是否使用持久性上下文并不重要。只有一个调用者会同时访问一个 bean 实例,因此即使持久性上下文不是线程安全的,EJB 也会防止对它的多次访问。可以把它想象成每个会话 bean 方法都应用了 synchronized 关键字。

我认为在 Servlet 中注入 EJB 的主要问题是性能。当多个请求排队等待为它们执行会话 bean 方法时,单个存根实例将成为主要的争用区域。

于 2010-08-27T13:52:24.220 回答
0

我认为简单的答案是你不能保证它是安全的。

原因是 EJB 规范中没有明确规定 EJB 主接口必须是线程安全的。该规范仅概述了服务器端部分的行为。您可能会发现客户端骨架实际上是线程安全的,但您需要查看您正在使用的库是如何实现它们的。注释部分将扩展为服务定位器,因此不会为您购买任何东西。

于 2009-03-06T12:10:44.677 回答