11

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...
    }
}

And is configured like this:

<bean id="myAspect" class="com.some.package.MyAspect" init-method="init" />

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.

1 Answers1

19

Is the init method only called once per IoC container

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!

is the httpServletRequest thread safe

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.

This whole behaviour is described in great details in 4.5.4.5 Scoped beans as dependencies:

[...] 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.

About ThreadLocal:

I prefer not to use a thread local.

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.

Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674
  • Tom, this is a great answer. Is it possible that Spring would have this documented somewhere that I could read up on? It was very difficult to find anything related to how the proxying actually works. Oh, and I don't need access to the request from within the init() -- that was me cheating and squeezing two questions into one :) –  May 10 '12 at 21:27
  • @BrianReindel: I included reference to the Spring documentation in my answer. – Tomasz Nurkiewicz May 10 '12 at 21:35
  • Hi Thomasz, will the code in answer work? Can you also give your opinion on "http://stackoverflow.com/questions/22923813/set-systems-property-in-controller-and-access-that-in-an-aspect" – hrishikeshp19 Apr 07 '14 at 23:07