All entries for Wednesday 17 August 2005

August 17, 2005

Spring AOP rocks (as expected ;))

Writing about web page

So in general, I am a big fan of the decorator pattern. This pattern very nicely allows you to have individual wrappers that deal with a single concern, for example:

interface SomeService {
  Object doSomething(final Object param);

if you want to wrap this with a caching wrapper, then a DelegateDecorator works well:

final class CachingSomeService implements SomeService {
  private final SomeService delegate;
  private final Map map = new HashMap();
  public CachingSomeService(final SomeService theDelegate) {
    this.delegate = theDelegate;

  public final Object doSomething(final Object param) {
    if (!map.contains(param)) {
      map.put(param, delegate.doSomething(param));
    return map.get(param);

you get the idea ;)

Well this works really well unless you only want to provide extra functionality for a single method, in which case you end up with a lot of methods that don't do anything except delegate, which is a bit smelly.

Spring AOP (actually just AOP) provides the answer ;) If you aren't familiar with, or haven't used AOP, then it takes a while to get your head around what it is, and how it works. Coupled with the fact that they use the most stupid terminology ever; it isn't easy :)

Anyways, rather then create another decorator, I now create an MethodInterceptor. This is a bit of code "wraps" the method I am adding functionality to. It looks like:

public Object invoke(final MethodInvocation methodInvocation) throws Throwable {
        Object[] args = methodInvocation.getArguments();
        Object param = args[0];
        if (!map.contains(param)) {
          map.put(param, methodInvocation.proceed());
        return map.get(param);

(one nasty thing is you loose type safety :()

I then need to tell Spring to wrap the bean with this interceptor. I do this by using a pointcut. A pointcut basically defines a position within code. Spring has a concept of an Advisor (combination of Advice and Pointcut), and a useful regexp based implements:

bean id="cachingAdvisor" class=""
    property name="advice" ref="cachingMethodInterceptor"
    property name="patterns"
        value .* value 

So we now have an Advisor detailing what we want to do, and where we want to do it.

The final piece is to "wrap" the "delegate", the original service implementation. We can do that through a FactoryBean, specifically, a ProxyFactoryBean:

bean id="myServiceTarget" class="MyServiceImpl"

   bean id="myService" class="org.springframework.aop.framework.ProxyFactoryBean"
    property name="proxyInterfaces" value="MyService"
    property name="target" ref="myServiceTarget"
    property name="interceptorNames"
        value cachingAdvisor value

Thus, when anyone asks for the bean "myService" they get a proxy that delegates all matching methods to cachingAdvisor. Any methods that don't match go straight through to the delegate (myServiceTarget).

Cool eh ;)

OK, as always there are pros and cons, pros:

  • cut down and empty delegateDecorators
  • configuration is done in the XML, where it should be
  • reuse advisor whereever (imagine a debugging advisor which will work for any method ;))


  • configuration is quite complicated
  • refactoring will break the advisor because of the lack of type safety. It will also potentially break the pointcut declaration
  • have to look at the configuration to see what is being done (which might actually be a good thing ;))
  • easy to break a whole chain of things because it is not being applied where you think it is
  • difficult to debug because you cannot see which classes are being used, you only see a "proxy$x" class.

Still all in all, an extremely powerful thing. It really comes into it's own when you start applying the same bit of code to lots of different places, i.e. transactions, security etc.

August 2005

Mo Tu We Th Fr Sa Su
Jul |  Today  | Sep
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31            

Search this blog



Most recent comments

  • Interesting… While I'm not completely convinced in such microbenchmarks, I'm pretty sure that 1ms … by Alexander Snaps on this entry
  • Hello. I bought the book yesterday. I was trying to find the source code for chapter 11 and chapter … by Suleman on this entry
  • by live mashup demo on this entry
  • Thanks mate ….. This blog was really helpful. by Maaz Hurzuk on this entry
  • Ty. Not directly helpful for my problem, but pointed me in the right direction. You will also get th… by Mike E. on this entry

Blog archive

Not signed in
Sign in

Powered by BlogBuilder