自动装配的 HTTPServletRequest bean 的 Spring AOP 和方面线程安全 [英] Spring AOP and aspect thread safety for an autowired HTTPServletRequest bean

查看:39
本文介绍了自动装配的 HTTPServletRequest bean 的 Spring AOP 和方面线程安全的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Spring 3 AOP,并且我有一个方面需要访问 HttpServletRequest.它看起来像这样:

I am using Spring 3 AOP, and I have an aspect that requires access to the HttpServletRequest. It looks something like this:

@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" />

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

Is the init method only called once per IoC container, even though this is an aspect, and is the httpServletRequest thread safe? If it is not, what is the best way to get at it during execution of the advice and have it be thread safe? If at all possible I prefer not to use a thread local.

推荐答案

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

Is the init method only called once per IoC container

每个 bean 实例调用一次.如果 bean 有一个单例范围(这也是方面的默认情况),它只会被调用一次.但是,您将无法访问 init() 方法中的 httpServletRequest - 还没有请求!

It is called once per every bean instance. If bean has a singleton scope (which is the default case for aspects as well), it will only be called once. However you won't have access to the httpServletRequest inside init() method - there is no request yet!

是 httpServletRequest 线程安全的

is the httpServletRequest thread safe

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

It is not but don't worry. This is actually much more complex than it looks like. You are injecting HTTP servlet request (and obviously there can be several requests available at the same time) into a singleton object. Which one is injected? None (all?) of them! Spring creates some sophisticated proxy (called scoped proxy) and every time you access methods of injected httpServletRequest it delegates them to current (to thread) request. This way you can safely run your aspects in several threads - each will operate on a different physical request.

4.5.4.5 作用域 bean 作为依赖项:

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

[...] If you want to inject (for example) an HTTP request scoped bean into another bean, you must inject an AOP proxy in place of the scoped bean. That is, you need to inject a proxy object that exposes the same public interface as the scoped object but that can also retrieve the real, target object from the relevant scope (for example, an HTTP request) and delegate method calls onto the real object.

关于ThreadLocal:

我不喜欢使用本地线程.

I prefer not to use a thread local.

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

Fortunately - Spring is using one for you. If you understand how ThreadLocal works - Spring puts current request into a thread local and delegates to thread-local instance when you access httpServletRequest proxy.

这篇关于自动装配的 HTTPServletRequest bean 的 Spring AOP 和方面线程安全的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆