How to declare After, After-Returning and After-Throwing advice using @AspectJ


This example shows how to use annotations to write an aspect using @AspectJ feature which was introduced in AspectJ 5. With this we do not need to define the advices and pointcuts in XML file.

In following example we have written an aspect named OurAspect.java which contains three advices named ourAfterAdvice(), ourAfterReturningAdvice() and ourAfterThrowingAdvice().

ourAfterAdvice() is a after-advice called every time after a method completes its execution, regardless whether the method has completed its execution successfully or not.

ourAfterReturningAdvice() is a after-returning advice called after a method completes its execution BUT only when method returns succesfully (no exception).

Similarly ourAfterThrowingAdvice() is a after-throwing advice called after a method completes its execution BUT  only when method could not be completed succesfully (i.e exception).

Steps

1) Write EmployeeService interface and its implementation EmployeeServiceImpl.
2) Write MainApp class which use methods of  EmployeeService interface.
3) Write aspect class named OurAspect.java using annotations.
4) Enabling @AspectJ support in XML file

Technologies Used
1) Spring-framework-3.0.6.RELEASE
2) Eclipse Java EE IDE Helios Release (Eclipse version 3.6)
3) Java SE 6




Code
EmployeeService.java

package examples.springaop.anno;

public interface EmployeeService{
   
    public void addEmployee();
    public String getEmployeebyName(String id);
   
}


EmployeeServiceImpl.java

package examples.springaop.anno;

public class EmployeeServiceImpl implements EmployeeService{
   
    public void addEmployee(){
       
        System.out.println("\n\n\naddEmployee() called. One Employee Added !");
    }
    public String getEmployeebyName(String id) throws NullPointerException{
       
        System.out.println("\n\n\ngetEmployeebyName() called.");
       

        if(id==null)
            throw new NullPointerException("ID cannot be null!");
       
        String empName = "Name"+id;
        return empName;
       
    }
   
}

MainApp.java

package examples.springaop.anno;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainApp{
public static void main(String args[]){
   
    ApplicationContext appContext = new ClassPathXmlApplicationContext("resources/ApplicationContext.xml");
    EmployeeService empService = (EmployeeService)appContext.getBean("empService");
   
    empService.addEmployee();
   
    empService.getEmployeebyName("id1");
   
    /*Causing exception to be thrown by this method*/
    empService.getEmployeebyName(null);
}
}

OurAspect.java

package examples.springaop.anno;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class OurAspect{

@Pointcut("execution(* examples.springaop.xml.EmployeeService.addEmployee(..))")
public void addEmpPointcut(){
   
}

@Pointcut("execution(* examples.springaop.xml.EmployeeService.getEmployeebyName(..))")
public void getEmpPointcut(){
   
}

@After("addEmpPointcut()|| getEmpPointcut()")
public void ourAfterAdvice(){
    System.out.println("This is After Advice, called after the method completion (in both Normal or Exceptional completion).");
   
 }

@AfterReturning("addEmpPointcut() || getEmpPointcut()")
public void ourAfterReturningAdvice(){
    System.out.println("This is After Returning Advice, called only when method completes its execution succesfully(i.e NO Exception)");
   
}

@AfterThrowing("addEmpPointcut()|| getEmpPointcut()")
public void ourAfterThrowingAdvice(){
    System.out.println("This is After Throwing Advice, called when method COULD NOT be completed succesfully(i.e Exception thrown)");
   
}

}

Here we have used @Aspect annotation on class OurAspect  to declare it as an aspect.

Next we have used @Pointcut annotation to declare pointcuts. @Pointcut is declared on methods. Here method names will be treated as pointcut ids, similar to what we do in

tag.(see example).

We have used @After, @AfterReturning and @AfterThrowing annotations to mark after, after-returning and after-throwing advices respectively.

Note how multiple pointcuts have been applied to single advice using ||. This means corresponding advice will be applied  to both methods defined in that @Pointcut annotation.

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-3.0.xsd

http://www.springframework.org/schema/aop

http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

<bean id="empService" class="examples.springaop.anno.EmployeeServiceImpl"/>

<bean id="empAspect" class="examples.springaop.anno.OurAspect"/>

<aop:aspectj-autoproxy/>

</beans>

For enabling @AspectJ support we have added following in XML file

<aop:aspectj-autoproxy/>

This will create proxies for those methods which are specified in pointcuts.

Note here pointcuts and advices are not defined in XMl file.

Output

addEmployee() called. One Employee Added !
This is After Advice, called after the method completion (in both Normal or Exceptional completion).
This is After Returning Advice, called only when method completes its execution succesfully(i.e NO Exception)

getEmployeebyName() called.
This is After Advice, called after the method completion (in both Normal or Exceptional completion).
This is After Returning Advice, called only when method completes its execution succesfully(i.e NO Exception)

getEmployeebyName() called.
This is After Advice, called after the method completion (in both Normal or Exceptional completion).
This is After Throwing Advice, called when method COULD NOT be completed succesfully(i.e Exception thrown)
Exception in thread "main" java.lang.NullPointerException: ID cannot be null!
    at examples.springaop.xml.EmployeeServiceImpl.getEmployeebyName(EmployeeServiceImpl.java:15)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)



Note the advices called after the three method calls in output.

We have applied after, after-returning and after-throwing advices to both methods. But not all advices have been called every time.

Since addEmployee()has not thrown  any exception so after-throwing advice is not been called after this method.

Similarly first call of getEmployeebyName() method returns successfully so after-returning advice got called but not the after-throwing advice. 

But second call to getEmployeebyName()has thrown exception. Here we have intentionally thrown the exception. As method has not completed its execution succesfully so after-throwing advice has been called not the after-returning advice.

Also note that after advice is called every time.

Jars Used

org.springframework.context-3.0.6.RELEASE.jar
org.springframework.core-3.0.6.RELEASE.jar
org.springframework.beans-3.0.6.RELEASE.jar
commons-logging-1.1.1.jar
org.springframework.asm-3.0.6.RELEASE.jar
org.springframework.aop-3.0.6.RELEASE.jar
com.springsource.org.aopalliance-1.0.0.jar
org.springframework.expression-3.0.6.RELEASE.jar
aspectjweaver-1.6.8.jar


I would like to know your comments and if you liked the article then please share it on social networking buttons.


1 comment: