将EJB作为实例变量注入servlet是否安全?

时间:2009-03-06 10:57:34

标签: servlets ejb-3.0 code-injection

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

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

在假设EJB的同一实例同时为多个请求提供服务的情况下,我的初衷是不。这似乎也是许多其他程序员的本能:Don't inject to servlets

但是我得出了错误的结论。显然,注入servlet的是一个代理,在容器下,容器实际上是用不同的实例为每个请求服务并保持线程安全吗?正如这个论坛所建议的那样:Do inject to servlets

似乎存在很多相互矛盾的观点。哪个是正确的???

4 个答案:

答案 0 :(得分:11)

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

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

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

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

答案 1 :(得分:3)

您的引用“不要注入servlet”没有提及ejbs或@ejb注释。它讨论的不是线程安全的对象,如PersistenceContext。

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

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

答案 2 :(得分:1)

这是一个混合包。

无状态会话bean可以注入并且是安全的。这是因为即使使用了一个存根实例,容器也会对这些方法进行序列化。

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

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

答案 3 :(得分:0)

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

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