Spring AOP AfterReturning Advice Annotation Example

0

Suppose we want to log or record information about a system joining or leaving a cluster, we can do it using an after advice aspect. An after advice will get executed regardless of whether a join point returns normally or throws an exception but if you want to log the information only when the machine successfully manages to join or leave then one can use an ‘After Returning’ advice.

AfterReturning Advice Annotation Example

In order to demonstrate AfterReturning annotation example, we will use the below test bean. It contains two methods concatenate(String, String) and sum(Integer, Integer).
If a and b both are null, concatenate(a, b) throws IllegalArgumentException.

TestBean:

package com.javarticles;

public class TestBean {
    
    public String concatenate(String a, String b) {
        System.out.println("methodA(" + a + ", " + b + ") called");
        if (a == null && b == null) {
            throw new IllegalArgumentException();
        }
        return a + b;
    }    
    
    public Integer sum(Integer a, Integer b) {
        System.out.println("sum(" + a + ", " + b + ")");        
        return a + b;
    }
}

Below is our first after returning advisor. Note that the class is annotated with @Aspect and the after returning advice is annotated with @AfterReturning.
The pointcut expression execution(* *.*(..)) used is generic so that any method which runs through successfully without an exception will become the joinpoint for the AfterReturning advice.

AopBean:

package com.javarticles;

import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class AopBean {

    @AfterReturning(value = "execution(* *.*(..))")
    public void afterAnyMethod() {
        System.out
                .println("@After AOP afterAnyMethod(), execution point: '* *.*(..)'");
    } 
}

We will declare AopBean and TestBean, and include execution(* *.*(..)) so that spring AOP can process the annotated class.

applicationContext.xml:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:aop="http://www.springframework.org/schema/aop"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">

 <bean id="testBean" class="com.javarticles.TestBean"/>
 <aop:aspectj-autoproxy/>
 <bean id="aopBean" class="com.javarticles.AopBean"/>
 
</beans>

Let’s run the main class now.

We will load the spring XML context, get the test bean, call concatenate() with arguments and then with null values.
We will also call sum() with coupe of integer arguments.

SpringAopAfterThrowingExample:

package com.javarticles;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringAopAfterThrowingExample {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
                "applicationContext.xml");
        try {
            TestBean testBean = (TestBean) context.getBean("testBean");
            System.out.println("Call testBean.concatenate(one, two)");
            testBean.concatenate("one", "two");
            try {
                System.out.println("********************************");
                System.out.println("Call testBean.concatenate(null, null)");
                testBean.concatenate(null, null);
            } catch (Exception e) {
                System.out.println("Exception: " + e.toString());
            }
            System.out.println("********************************");
            System.out.println("Call testBean.sum(2,3)");
            testBean.sum(2, 3);
        } finally {
            context.close();
        }
    }
}

You can see when the method runs successfully without exception AfterReturning advice is executed. In case of NullPointerException, AfterReturning advice is not called.

Output:

Call testBean.concatenate(one, two)
methodA(one, two) called
@After AOP afterAnyMethod(), execution point: '* *.*(..)'
********************************
Call testBean.concatenate(null, null)
methodA(null, null) called
Exception: java.lang.IllegalArgumentException
********************************
Call testBean.sum(2,3)
sum(2, 3)
@After AOP afterAnyMethod(), execution point: '* *.*(..)'

Using return value as an argument in AfterReturning annotated method

If you want to access the return value or just want the AfterReturning method to execute only for certain return types then you need to add a returning attribute to the @AfterReturning annotation. The value of this attribute should be the argument name of this advice method and then the return value will get automatically mapped to the argument passed in. At runtime, Spring AOP will pass in the return value through this argument.

AopBean:

package com.javarticles;

import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class AopBean {

    @AfterReturning(value = "execution(* *.*(..))")
    public void afterAnyMethod() {
        System.out
                .println("@After AOP afterAnyMethod(), execution point: '* *.*(..)'");
    }  

    @AfterReturning(value = "execution(* *.*(..))", returning="result")
    public void afterAnyResult(Object result) {
        System.out
                .println("@After AOP afterAnyResult(" + result + "), execution point: '* *.*(..)'");
    }
    
    @AfterReturning(value = "execution(* *.*(..))", returning="result")
    public void afterConcatenate(String result) {
        System.out
                .println("@After AOP afterConcatenate(" + result + "), execution point: '* *.*(..)'");
    } 
    
    @AfterReturning(value = "execution(* *.*(..))", returning="result")
    public void afterSum(Integer result) {
        System.out
                .println("@After AOP afterSum(" + result +"), execution point: '* *.*(..)'");
    } 
}

SpringAopAfterThrowingExample:

package com.javarticles;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringAopAfterThrowingExample {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
                "applicationContext.xml");
        try {
            TestBean testBean = (TestBean) context.getBean("testBean");
            System.out.println("Call testBean.concatenate(one, two)");
            testBean.concatenate("one", "two");
            try {
                System.out.println("********************************");
                System.out.println("Call testBean.concatenate(null, null)");
                testBean.concatenate(null, null);
            } catch (Exception e) {
                System.out.println("Exception: " + e.toString());
            }
            System.out.println("********************************");
            System.out.println("Call testBean.sum(2,3)");
            testBean.sum(2, 3);
        } finally {
            context.close();
        }
    }
}
As you can see, in case of any exception none of the @AfterReturning advisors are called. Also the after returning advice with return type are called for joinpoints that match the return type.
Output:
Call testBean.concatenate(one, two)
methodA(one, two) called
@After AOP afterAnyMethod(), execution point: '* *.*(..)'
@After AOP afterAnyResult(onetwo), execution point: '* *.*(..)'
@After AOP afterConcatenate(onetwo), execution point: '* *.*(..)'
********************************
Call testBean.concatenate(null, null)
methodA(null, null) called
Exception: java.lang.IllegalArgumentException
********************************
Call testBean.sum(2,3)
sum(2, 3)
@After AOP afterAnyMethod(), execution point: '* *.*(..)'
@After AOP afterAnyResult(5), execution point: '* *.*(..)'
@After AOP afterSum(5), execution point: '* *.*(..)'

Download the source code

This was an example about Spring AOP @AfterReturning annotated advice.

You can download the source code here: springAopAfterReturningAdviceAnnotationExample.zip
Share.

Comments are closed.