Monday, 26 December 2011

Accessing Parameters from a Spring AOP 2 Pointcut

I recently had a question from one of our customers, asking how you can access and modify the parameters in Spring AOP 2 - we didn't refer to this on the course as we concentrated on the most common uses of AOP - so here's a quick blog post showing how to do this.

If you haven't used our Spring Fundamentals training course, the full chapter covering AOP is available as a preview below (you can play this at full screen to see the full detail):


Modifying parameters in advice is a very powerful thing thing to do (be careful - powerful means dangerous!), but it can be achieved easily in Spring AOP 2, using the AspectJ syntax.

On the course, we write a performance timing advice class, using Around advice. I've taken the annotation based version from the course, and I've modified it to take one of the incoming parameters (the customerId) and to change it's value before passing it on to the target method.
@Advice
public class ModifyIncomingParameterAdvice
{
 @Pointcut("execution(* com.virtualpairprogrammers.calls.CallHandlingService.recordCall(..)) && args (customerid, call, actions)")
 public void trapRecordCall(String customerid, Call call, Collection actions) {}
 
 @Around("trapRecordCall(customerid, call, actions)")
 public Object changeTheIncomingCustomerId(ProceedingJoinPoint method, String customerid, Call call, Collection actions) throws Throwable
 {
  System.out.println("Asked to record a call for customer id " + customerid);
    
  // run the target code - but with a different customer id!
  String newCustomerId = customerid + "NEW";
  
  // we can pass parameters as an object array - you must get the correct number of 
  // parameters as the target is expecting, or you get a runtime exception.
  Object returnValue = method.proceed(new Object[] {newCustomerId, call, actions});
    
  return returnValue;
 }
}

Notice the use of the args() in the pointcut. This is the important part of this technique. It is applying the pointcut only to invocations of methods called recordCall that have exactly three incoming parameters. And these three parameters are given names which we can use as parameters to the Around advice.

If you want to use the XML form of AOP (I prefer XML for AOP in Spring), then you would just change the pointcut in your Spring XML - a rough example follows:
 
 
 
 
 
  
   
  
 
Notice that I had to escape the ampersands (&) in the pointcut, as you will get an XML error otherwise.

Now, this is a made up and probably useless example, but I hope you can see the power of this. I guess that most projects will very rarely want to use this technique, but I'd be very interested if you've used this on your real world projects - do tell me if you have some examples.

2 comments:

  1. I found your Spring and Spring MVC tutorials very helpful, and I've been using Spring/MVC in several of my projects. I recently read that since Spring 3.0.4, multiple file upload is now supported. Currently I'm doing a single file upload using Spring Framework 3.0.6, but I have a requirement for a multiple file upload. Could you point me in the right direction on getting more information and examples on how to utilize Spring 3 Framework and Spring MVC to do multiple file uploads?

    ReplyDelete
  2. Thank you, this helped me especially escaping xml error

    ReplyDelete