Adding multiple advices in Spring AOP

Adding multiple advices in Spring
In this example we will see how to add multiple advices to methods in the target bean object. Adding multiple advices is necessary at times to differentiate the cross-cutting concerns. For example, in an advice you will want to log the details such as when the method is invoked and how much time it took to execute and in another advice you will want to check if the user has valid credentials to access that method etc.
Here these are two different aspects and there must be a way to ensure that they are separated from each other.
To do so, we treat each task as a new advice and write them separately in two different classes.

Theme of the application

The theme of the application is to illustrate adding multiple advices to methods in a target bean. In this example, we will have two advices
  1. Logging advice
  2. Around Message Advice
Logging advice is prints information that the method has started and it has ended execution.
Around message advice appends two messages (at start and end) of the method execution.
The method takes a string object and prints it.

Create a project in eclipse

  1. File -> New -> Project -> Java Project
  2. Give the project name spring40 and click Finish 
  3. Now, the project is created.
  4. Under the Project Explorer (in the sidebar) you will see spring40. If you aren't able to see Project Explorer, go to Window menu -> Show view -> Project Explorer.
  5. Right click on the spring40 and click Properties
  6. On the left side, click on Java Build Path.
  7. Select the Libraries tab and then click on Add External Jars
  8. Now, add these jar files starting with: spring-core, aop-alliance, spring-aop, commons-logging
  9. Click on OK and then you are read

To create a class

In the Project Explorer, navigate to spring40 and right click on spring40. Then go to New -> Class and give the name of the class as defined below.

Project structure


PrinterBean.java

package spring40;

public class PrinterBean {

    public void print(String msg) {
        System.out.print(msg);
    }

}

LoggingAdvice.java

package spring40;

import org.aopalliance.intercept.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class LoggingAdvice implements MethodInterceptor {

    private static Log log;

    static {
        log = LogFactory.getLog(LoggingAdvice.class);
    }

    public Object invoke(MethodInvocation mi) throws Throwable {
        Object val = null;

        if (log.isInfoEnabled()) {
            String name = mi.getMethod().getName() + "(\""+ mi.getArguments()[0] + "\");";
            log.info("Invoking the method " + name);
            val = mi.proceed();
            log.info("Method " + name + " executed successfully.");
        }

        return val;
    }

}

This class logs that the method has started execution and it has ended execution. Using the LogFactory.getLog() method we can obtain a Log object which contains the method info() that logs the information to the console.

AroundMessageAdvice.java

package spring40;

import org.aopalliance.intercept.*;

public class AroundMessageAdvice implements MethodInterceptor{

    public Object invoke(MethodInvocation mi) throws Throwable
    {       
        System.out.print("The message is ");
        Object val=mi.proceed();
        System.out.println(".");
       
        return val;
    }
}

The MethodInterceptor contains the invoke() method which takes MethodInterceptor object which contains the method proceed(). This method invokes the method to which this advice is applied.
Here The message is is printed before calling the method and a dot is printed after calling the method.


SpringPrg.java - Main class

package spring40;

import org.springframework.aop.framework.ProxyFactory;

public class SpringPrg {

    public static void main(String args[]) {
       
        // Create target bean object
        PrinterBean pb = new PrinterBean();

       
        ProxyFactory pf = new ProxyFactory();
        pf.setTarget(pb);
       
        // Adding multiple advices
        // advices are applied in order they are added
        pf.addAdvice(new LoggingAdvice());
        pf.addAdvice(new AroundMessageAdvice());
       
       
        // Get the proxied bean object
        PrinterBean bean=(PrinterBean)pf.getProxy();
       
        // call the methods for which the advices
        // are wrapped
        bean.print("Rama");
        bean.print("Siva");
    }

}
In this class, we have created a target bean object, a ProxyFactory object and set the target object to the bean object, created two advice objects and added them.
The getProxy() method returns the bean object whose for whose methods the advice will be applied.
The print() method when called from the object bean will execute the advice code. When you invoke print() from pb then the method will not print both logging advice and around message advice.

Output 


Apr 08, 2014 3:01:23 PM spring40.LoggingAdvice invoke
INFO: Invoking the method print("Rama");
The message is Rama.
Apr 08, 2014 3:01:23 PM spring40.LoggingAdvice invoke
INFO: Method print("Rama"); executed successfully.
Apr 08, 2014 3:01:23 PM spring40.LoggingAdvice invoke
INFO: Invoking the method print("Siva");
Apr 08, 2014 3:01:23 PM spring40.LoggingAdvice invoke
INFO: Method print("Siva"); executed successfully.
The message is Siva.

Also see before advice, after advice and around advice

No comments: