2013-06-25 55 views
2
@WebListener 
public class AllRequestsWebListener implements ServletRequestListener { 

    @Inject HttpRequestProducer producer; 

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

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

@RequestScoped 
public class HttpRequestProducer { 
... 
} 

我不知道HOWTO注入请求bean作为方法参数,因此,我可以猜测,它会正常工作时,请求豆注入的ThreadLocal。有人能解释我是如何以线程安全的方式实现的吗?

回答

0

基于直觉的答案

我相信它是线程安全的,因为请求范围是线程安全的(会话及以上的都没有,作为一个用户可以同时打开多个浏览器会话和使用相同的会话ID)

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

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

规格支持的答案

难的是要找到这要求在规范的确凿证据。

我查看了CDI规范,无法快速找到确切的证据表明@RequestScoped对象是线程安全的(例如使用线程本地),但是我假定@RequestScoped bean使用与作用域bean相同的作用域Java EE 5中(见here

在有这个条款是有趣:

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

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

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

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

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

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

1

你在bean中注入的是代表真实交易的代理。代理总是将调用转发到正确的豆