Sunday, June 26, 2011

Spring AOP Scoped Proxies

In this post I'll be discussing the Spring AOP Scoped Proxies as a way to expand the scope of the beans managed by the spring IoC container. So far we know two types of scopes common to the IoC container: Singleton, just one instance per container, and Prototype, one instance per client (of the bean). The previous two scopes can give us an idea of stateless/stateful beans but in some context there are other contexts that can be useful, for example in a web application we can think on the scope of a request or the scope of a session to make parts of the application that only makes sense on a web context.

It's true that the right thing to do when we're designing our backend is to try and do the whole functionality as independent of the context as possible but sometimes having a bean that depends on the context makes the application logic so simple, elegant and easy to code that we're tempted to make things that way, for example, if we're coding an application logic that depends a lot on the information of the currently logged user it would be really handy to have in our bean something like this:
 @Autowired
private CurrentUser currentUser
And then get the data as we please. But the thing is with the prototype scope or singleton scope it would be very difficult to achieve this, specially when a lot of users ar accessing the app simultaneously. So to this purpose we'll configure the AOP scoped proxies.

First of all, we'll speak about the dependencies we need:
  • Spring AOP, to have the AOP functionality in our application.
  • CGLIB if we're going to have proxies for classes that doesn't implement any interface.
Then, we'll have our standard configuration but apart from that, some special configuration so spring can tell which request matches to which thread and thus access the session and request scopes.

We'll add the following lines in our web.xml file:
   <listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
Finally we configure the bean to be session scoped or request scoped:

 @Service
@Scope(value="session",proxyMode= ScopedProxyMode.TARGET_CLASS)
public class CurrentUser implements Serializable {
//session data here
}

If we're configuring our beans in the XML fashion, then we add the tag:
 <bean ... scope="session"> 
<aop:scoped-proxy/>
</bean>
To our bean definition and that's it. Really easy and really clean because our bean logic doesn't get dirty with Servlet spec classes and if we need to switch this logic to be for instance a desktop application, we can always switch the bean to be singleton and take care of it by ourselves.

3 comments:

  1. Hello,

    Thanks for your useful tips.

    When I put the tag as you mention, I got the error as follows:
    cvc-complex-type.2.4.a: Invalid content was found starting with element 'listener'. One of '{"http://www.springframework.org/schema/
    beans":import, "http://www.springframework.org/schema/beans":alias, "http://www.springframework.org/schema/beans":bean,
    WC[##other:"http://www.springframework.org/schema/beans"]}' is expected.

    I am new in Spring. Please help if you have a chance.

    Regards,

    Tom

    ReplyDelete
  2. I meant I put this listener tag in web.xml, I got the error above.

    Tom

    ReplyDelete