以下请求范围注入线程安全吗?

时间:2013-06-25 06:49:17

标签: servlets cdi

@WebListener
public class AllRequestsWebListener implements ServletRequestListener {

    @Inject HttpRequestProducer producer;

    public void requestInitialized(ServletRequestEvent sre) {
    producer.requestInitialized(sre);
    }
}

...

@RequestScoped
public class HttpRequestProducer {
...
}

我不知道如何将request-bean注入方法参数,因此我可以猜测,当Request-bean注入为threadLocal时它将正常工作。有人能解释一下它是如何以线程安全的方式实现的吗?

2 个答案:

答案 0 :(得分:1)

你在bean中注入的是代表真实交易的代理。代理将始终将调用转发给正确的bean

答案 1 :(得分:0)

基于直觉的回答

我认为它是线程安全的,因为请求范围是线程安全的(会话及以上不是,因为用户可以打开多个浏览器会话并使用相同的会话ID)

我测试了它,虽然它是经验证据,但注入的HttpRequestProducer每个请求获得一个新实例。

请注意,requestInitializedrequestDestroyed可以(实际上是)不同的线程,因此如果您打算在两种方法上使用相同的注入对象,我将进一步调查。

规范支持的答案

困难的部分是在规范中找到这个主张的确凿证据。

我查看了CDI规范并且无法快速找到确凿的证据证明@RequestScoped对象是线程安全的(例如使用线程本地)但是我假设@RequestScoped bean使用与Java中的scoped bean相同的范围EE 5 :(见here

在那里,这个条款很有意思:

  

在多线程中控制对共享资源的并发访问   服务器,可以访问共享资源   同时。除了范围对象属性,共享资源   包括内存中的数据(例如实例或类变量)和   外部对象,如文件,数据库连接和网络   连接。

     

在几种情况下可能会出现并发访问:

     
      
  • 多个Web组件访问存储在Web上下文中的对象。

  •   
  • 多个Web组件访问存储在会话中的对象。

  •   
  • 访问实例变量的Web组件中的多个线程。   Web容器通常会创建一个线程来处理每个请求。   如果要确保servlet实例仅处理一个请求   一次,servlet可以实现SingleThreadModel接口。如果   一个servlet实现了这个接口,你保证没有两个   线程将在servlet的服务方法中并发执行。一个   Web容器可以通过同步访问来实现此保证   servlet的单个实例,或者维护一个Web池   组件实例并将每个新请求分派给一个免费的   实例。此接口不会阻止同步问题   Web组件访问共享资源的结果,例如   静态类变量或外部对象。另外,Servlet   2.4规范不推荐使用SingleThreadModel接口。

  •   

所以从理论上讲,似乎对象本身每个请求线程都有一个实例,但是我找不到任何支持这个实例的确凿证据。