Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Servlets 将EJB作为实例变量注入servlet是否安全?_Servlets_Ejb 3.0_Code Injection - Fatal编程技术网

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

Servlets 将EJB作为实例变量注入servlet是否安全?,servlets,ejb-3.0,code-injection,Servlets,Ejb 3.0,Code Injection,我们都知道,在web层中,可能只存在一个给定Servlet的实例来服务多个请求。这可能导致实例变量中出现线程问题 我的问题是,将@EJB注释作为实例变量注入servlet是否安全 我最初的直觉是否定的,因为我假设同一个EJB实例将同时为多个请求提供服务。这似乎也是许多其他程序员的本能: 然而,我得出了错误的结论。很明显,注入servlet的是一个代理,容器是否实际使用不同的实例为每个请求提供服务并维护线程安全?正如本论坛所建议的那样: 似乎有很多相互矛盾的意见。哪个是正确的?我认为简单的答案是你

我们都知道,在web层中,可能只存在一个给定Servlet的实例来服务多个请求。这可能导致实例变量中出现线程问题

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

我最初的直觉是否定的,因为我假设同一个EJB实例将同时为多个请求提供服务。这似乎也是许多其他程序员的本能:

然而,我得出了错误的结论。很明显,注入servlet的是一个代理,容器是否实际使用不同的实例为每个请求提供服务并维护线程安全?正如本论坛所建议的那样:


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

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

原因是EJB规范中没有明确规定EJB主接口必须是线程安全的。规范仅概述了服务器端部件的行为。您可能会发现,客户机框架实际上是线程安全的,但是您需要了解您正在使用的库是如何实现它们的。注释部分只会扩展为服务定位器,这样就不会给您带来任何好处

您的参考“不要注入servlet”没有提到任何关于ejb或@ejb注释的内容。它讨论的对象不是线程安全的,比如PersistenceContext

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


因此,基于EJB3.0规范,使用@EJB注释从Servlet获取EJB是一种标准做法。

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

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

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

只要遵守上述规则,在Servlet中注入无状态Bean应该是线程安全的,因为它是一个混合包

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

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


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

这个答案就其本身而言是正确的,但它没有解决OP的线程安全问题。我相信下面的inferreddesign的答案应该是正确的。我想用@Inject(CDI,JEE 6)注入的EJB也同样安全,不是吗?存根将被同步,但我希望它将很快被分派到一个池EJB中去做真正的工作。除非存根在整个调用期间持有锁,否则这将是一个非常糟糕的实现选择。。。