AfterReturningAdvice Example in Spring AOP

After returning advice in Spring
Here is an example illustrating after-returning-advice in Spring AOP. The after advice is the advice that is given to a method after it is executed.
In simple words, it is nothing more than code that is executed after the method call. As the method is executed, you will have access to the value returned by that method.

Theme of the application

The theme of the application is to illustrate after-returning-advice. As this advice can have access to the value returned by the method to which this advice is applied, we can check if the value returned by that method is desired or not. In this example, the method code contains generating a random integer below 3 and greater than 0. Now, if the value returned equals 1, the method is called again.

Create a project in eclipse

  1. File -> New -> Project -> Java Project
  2. Give the project name spring37 and click Finish 
  3. Now, the project is created.
  4. Under the Project Explorer (in the sidebar) you will see spring37. If you aren't able to see Project Explorer, go to Window menu -> Show view -> Project Explorer.
  5. Right click on the spring37 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 spring37 and right click on spring37. Then go to New -> Class and give the name of the class as defined below.
 

Project structure


WorkerBean.java

This class contains the method for which the advice will be applied.

package spring37;

import java.util.Random;

public class WorkerBean {

private static Random r=new Random();

    public int generateRandomInt()
    {
        return r.nextInt(3);
    }

ReturnValChecker.java  - Advice class

package spring37;

import java.lang.reflect.Method;

import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.framework.ProxyFactory;

public class ReturnValChecker implements AfterReturningAdvice{

private ProxyFactory pf;

    public ReturnValChecker(ProxyFactory pf)
    {
        this.pf=pf;
    }

    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args,
            Object target) throws Throwable {
       
        int i=(Integer)returnValue;
       
            if(i==1)
            {
                System.out.println("i=1, so calling "+method.getName()+"() again");
                WorkerBean bean=(WorkerBean)pf.getProxy();
                bean.generateRandomInt();
            }
            else
            {
                System.out.println("i is greater than 1, no problem!");
            }
    }
}

This class' constructor takes in a ProxyFactory object which will be used to get the bean object for whose methods the advice is applied to.
The method afterReturning() is present in AfterReturningAdvice interface.

The method prototype: This method takes four parameters, as you can see,

Object returnVal: This is the value returned by the method to which this advice is applied.
Method method: This is a class of the java.lang.reflect package which is used to get information about the method such as its name, types of arguments etc.
Object[] args: This parameter represents the values of the argument(s) passed to the method. Here, the method generateRandomInt() takes no arguments.
Object target: This is a reference to the object that is set as target object in the ProxyFactory.

In this method, we have taken the return value to a variable i and using the condition, we have checked if the value equals 1, if so, then using the getProxy() method, the object to whose methods the advice is applied is taken and the method generateRandomInt() is called again. This continues until i is not equal to 1.

SpringPrg.java - Main class

package spring37;

import org.springframework.aop.framework.ProxyFactory;

public class SpringPrg {

    public static void main(String args[])
    {
        // Create bean object
        WorkerBean wb=new WorkerBean();
       
        // Create a ProxyFactory object
        ProxyFactory pf=new ProxyFactory();
       
        // Create advice object
        ReturnValChecker rc=new ReturnValChecker(pf);
       
        // Set the target object
        pf.setTarget(wb);
       
        // Add advice
        pf.addAdvice(rc);
       
        // Get the proxied bean object
        WorkerBean bean=(WorkerBean)pf.getProxy();
       
        // Start the work
        bean.generateRandomInt();
    }

This class will a ProxyFactory object through which we can wrap the advice to a target bean object.
The target bean object is the bean object to whose methods the advice should be applied.
The addAdvice() method adds the specified advice to the target bean. You can add as many as advices as you want and they will be executed in the order they were added.
The getProxy() method returns the bean object to which the advice is applied. Now, when you call the generateRandomInt() method, after the value is returned, the advice is executed and then if the value equals 1, it is called again. So, it is damn sure that the value returned by the generateRandomInt() will always be other than 1. But if you call it normally, i.e. wb.generateRandomInt() you may also get 1. But with the proxied bean object, you will not.
Also see MethodBeforeAdvice example

No comments: