自动连线HttpServletRequestbean的Spring AOP和方面线程安全

自动连线HttpServletRequestbean的Spring AOP和方面线程安全,spring,servlets,thread-safety,aop,spring-aop,Spring,Servlets,Thread Safety,Aop,Spring Aop,我使用的是Spring3AOP,我有一个方面需要访问HttpServletRequest。它看起来像这样: @Aspect public class MyAspect { @Autowired private HttpServletRequest httpServletRequest; public void init() { // Do something once... } @Before("my pointcut here...

我使用的是Spring3AOP,我有一个方面需要访问HttpServletRequest。它看起来像这样:

@Aspect
public class MyAspect {

    @Autowired
    private HttpServletRequest httpServletRequest;

    public void init() {
        // Do something once...
    }

    @Before("my pointcut here...")
    private void myMethod() {
        // I need the httpServletRequest...
    }

    @After("my pointcut here...")
    private void myOtherMethod() {
        // I need the httpServletRequest...
    }
}
<bean id="myAspect" class="com.some.package.MyAspect" init-method="init" />
配置如下:

@Aspect
public class MyAspect {

    @Autowired
    private HttpServletRequest httpServletRequest;

    public void init() {
        // Do something once...
    }

    @Before("my pointcut here...")
    private void myMethod() {
        // I need the httpServletRequest...
    }

    @After("my pointcut here...")
    private void myOtherMethod() {
        // I need the httpServletRequest...
    }
}
<bean id="myAspect" class="com.some.package.MyAspect" init-method="init" />

是否每个IoC容器只调用一次init方法,即使这是一个方面,并且httpServletRequest线程安全?如果不是,那么在建议执行期间获得建议并使其成为线程安全的最佳方法是什么?如果可能的话,我宁愿不使用本地线程

是否每个IoC容器只调用一次init方法

每个bean实例调用一次。如果bean有一个单例作用域(这也是方面的默认情况),那么它将只被调用一次。但是,您将无法访问
httpServletRequest
内部
init()
方法-还没有请求

httpServletRequest线程安全吗

不是,但别担心。这实际上比看起来要复杂得多。您正在将HTTPServlet请求(显然,可以同时有多个请求可用)注入到一个单例对象中。哪一个是注射的?一个也没有!Spring创建了一些复杂的代理(称为作用域代理),每次访问httpServletRequest的方法时,它都会将它们委托给当前(线程)请求。通过这种方式,您可以在多个线程中安全地运行方面—每个线程将在不同的物理请求上运行

以下内容详细描述了整个行为:

[…]如果希望将一个HTTP请求范围的bean注入(例如)另一个bean,则必须注入一个AOP代理来代替范围的bean。也就是说,您需要注入一个代理对象,该代理对象公开与作用域对象相同的公共接口,但也可以从相关作用域(例如HTTP请求)检索真实的目标对象,并将方法调用委托给真实对象

关于
ThreadLocal

我不喜欢使用本地线程


幸运的是,Spring正在为您使用一个。如果您了解
ThreadLocal
的工作原理,那么当您访问
httpServletRequest
代理时,Spring会将当前请求放入线程本地,并委托给线程本地实例。

Tom,这是一个很好的答案。有没有可能Spring会在某个我可以阅读的地方记录下这一点?很难找到任何与代理实际工作方式相关的内容。哦,我不需要从init()中访问请求——那是我作弊,把两个问题挤成一个:)@BrianReindel:我的答案中包含了对Spring文档的引用。嗨,Thomasz,答案中的代码会工作吗?你能不能也谈谈你对“”的看法