logo

Spring AOP With AspectJ Annotation Example


Show

In the Spring framework, an AspectJ Annotation refers to a type of declaring aspects that are treated as regular Java classes. These aspects are introduced by the AspectJ project as an integral part of AspectJ 5 during its release. It is recommended to use Spring AspectJ AOP implementation instead of Spring 1.2 old-style AOP implementation as AspectJ is supported by many of the AOP frameworks. It is very easy to use and provides you with more control. In AspectJ, you can intercept methods easily. The popularity of AspectJ can be identified by the support from Spring that uses POJO aspects written with AspectJ annotations in its AOP framework.

We Can Perform Spring AOP AspectJ Implementation in the Following Two Ways:

  • By annotation
  • By XML configuration

But in this example, we will show you how to implement AspectJ in Spring AOP by the use of annotations. The advice will be created by the use of the following annotations:

Spring AspectJ AOP implementation provides many annotations but some of the common annotations are as follows:

@Aspect declares the class as an aspect.

@Pointcut declares the pointcut expression.

@Before annotation declares the before advice. It is implemented before invoking the actual method.

@After declares the after advice. It is implemented after calling the actual method and before returning the result.

@AfterReturning declares the after returning advice. It is executed after invoking the actual method and before returning the result. But you can get the result value in the advice.

@Around declares the around advice. It gets executed before and after calling the actual method.

@AfterThrowing declares the throws advice. It is implemented if the actual method throws an exception.

Now we will Understand the Above Annotations Briefly:

Pointcut

In Spring AOP, a pointcut is used as an expression language or pattern that defines the pointcut. The name can also be used as an alternative for the pointcut expression. A pointCut is a set of JoinPoint(s) where advice gets executed or it should be. It helps using specific JoinPoints to implement the advice.

Let's take a look at a simple code example of PointCut.

@Pointcut("execution(* Operation.*(..))")  
private void doSomething() {} 

Here, doSomething() is used as the name of the PointCut expression. We can apply this name to all the methods of Operation class without any concern about the return type.

Pointcut Expressions examples:

@Pointcut("execution(public * *(..))") 

It will be applied to all public methods.

@Pointcut("execution(public Operation.*(..))")  

This is applied to all the public methods of Operation class.

@Pointcut("execution(* Operation.*(..))")

This is applied to all the methods of Operation class.

@Pointcut("execution(public Employee.set*(..))")  

This is applied to all the public setter methods of Employee class.

@Pointcut("execution(int Operation.*(..))") 

This is applied to all the methods of the Operation class that returns an int value.

@Before Example

Also known as before advice, this annotation is applied before the actual business logic method. With the help of this annotation, you can complete any task such as conversion, authentication, etc. Before advice is used in Aspect-Oriented Programming of Spring to get the cross-cutting.

Now we will create a class named Operation.java that includes actual business logic.

package com.intellinuts;  
public class Operation{  
    public void msg(){System.out.println("msg method invoked");}  
    public int m(){System.out.println("m method invoked");return 2;}  
    public int k(){System.out.println("k method invoked");return 3;}  
} 

Now, we create another class named TrackOperation.java that includes @Before advice annotation.

package com.intellinuts;  

import org.aspectj.lang.JoinPoint;  
import org.aspectj.lang.annotation.Aspect;  
import org.aspectj.lang.annotation.Before;  
import org.aspectj.lang.annotation.Pointcut;  

@Aspect  
public class TrackOperation{  
    @Pointcut("execution(* Operation.*(..))")  
    public void k(){}//pointcut name  

    @Before("k()")//applying pointcut on before advice  
    public void myadvice(JoinPoint jp)//it is advice (before advice)  

    {  
        System.out.println("additional concern");  
        //System.out.println("Method Signature: " + jp.getSignature());  
    }  

}  

Now it's time to create the bean definition file named 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.xsd">  

    <bean id="opBean" class="com.intellinuts.Operation"> </bean>  
    <bean id="trackMyBean" class="com.intellinuts.TrackOperation"></bean>  
    <bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"></bean>  

</beans>  

Now, we will create a Test.java class that contains the actual method. This class will get the bean information from the applicationContext.xml file by calling the getBean() method and display the output.

package com.intellinuts;    
import org.springframework.context.ApplicationContext;  
import org.springframework.context.support.ClassPathXmlApplicationContext;  
public class Test{  
    public static void main(String[] args){  
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");  
        Operation e = (Operation) context.getBean("opBean");  
        System.out.println("calling msg...");  
        e.msg();  
        System.out.println("calling m...");  
        e.m();  
        System.out.println("calling k...");  
        e.k();  
    }  
}  

The output of the above program will be:

calling msg...  
additional concern  
msg() method invoked  
calling m...  
additional concern  
m() method invoked  
calling k...  
additional concern  
k() method invoked

In the above result, you can see the additional concern is displayed before calling msg(), m(), and k() methods. In case, if we make a change in the pointcut expression like this:

@Pointcut("execution(* Operation.m*(..))") 

Now, in this case, extra concerns will be applied to those methods that start with m in Operation class. The output looks like this:

calling msg...  
additional concern  
msg() method invoked  
calling m...  
additional concern  
m() method invoked  
calling k...  
k() method invoked

In the above output, we can see that the additional concern is not mentioned before calling the k() method.

@After Example

After advice annotation of AspectJ is denoted as @After is applied after calling the actual business logic methods whether an exception is thrown or not. We can maintain the tasks like a log, security, notification, etc; by using After Advice annotation. This annotation aims to achieve the cross-cutting of concerns.

Before going further, we assume that Operation.java, applicationContext.xml, and Test.java files are the same as we show in the previous example.

Now we create an aspect class named TrackOperation.java that includes after advice and mentions ‘additional concern’.

package com.intellinuts;  
import org.aspectj.lang.JoinPoint;  
import org.aspectj.lang.annotation.Aspect;  
import org.aspectj.lang.annotation.After;  
import org.aspectj.lang.annotation.Pointcut;  

@Aspect  
public class TrackOperation{  
    @Pointcut("execution(* Operation.*(..))")  
    public void k(){}//pointcut name  
    @After("k()")//applying pointcut on after advice  
    public void myadvice(JoinPoint jp)//it is advice (after advice)  
    {  
        System.out.println("additional concern");  
        //System.out.println("Method Signature: " + jp.getSignature());  
    }  

}  

So the output of the above program is viewed as:

calling msg...  
msg() method invoked  
additional concern  
calling m...  
m() method invoked  
additional concern  
calling k...  
k() method invoked  
additional concern

We can see in the output that the phrase additional concern is displayed after calling msg(), m(), and k() methods.

@AfterReturning Example

In Spring AOP, after returning is used as advice that runs after the successful (where PointCut expression is matched) method execution. If an exception is thrown by the method, this advice cannot be invoked. We can get the result in the advice after the implementation of the returning advice.

To use @AfterReturning, we just create the class named Operation.java that contains business logic.

package com.intellinuts;  
public class Operation{  
    public int m(){System.out.println("m() method invoked");return 2;}  
    public int k(){System.out.println("k() method invoked");return 3;}  
}

Now we create a class named TrackOperation.java that includes after returning advice.

package com.intellinuts;  

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

@Aspect  
public class TrackOperation{  
    @AfterReturning(  
              pointcut = "execution(* Operation.*(..))",  
              returning= "result")  

    public void myadvice(JoinPoint jp,Object result)//it is advice (after returning advice)  
    {  
        System.out.println("additional concern");  
        System.out.println("Method Signature: " + jp.getSignature());  
        System.out.println("Result in advice: "+result);  
        System.out.println("end of after returning advice...");  
    }  

}  

We will assume that applicationContext.xml is the same as given in the @Before advice example.

Now, we will create a Test.java class that gets the bean information from the XML configuration file and calls the getBean() method. This class calls the actual methods.

package com.intellinuts;  
import org.springframework.context.ApplicationContext;  
import org.springframework.context.support.ClassPathXmlApplicationContext;  
public class Test{  
    public static void main(String[] args){  
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");  
        Operation e = (Operation) context.getBean("opBean");  
        System.out.println("calling m...");  
        System.out.println(e.m());  
        System.out.println("calling k...");  
        System.out.println(e.k());  
    }  
}  

The output of the above is:

calling m...  
m() method invoked  
additional concern  
Method Signature: int com.intellinuts.Operation.m()  
Result in advice: 2  
end of after returning advice...  
2  
calling k...  
k() method invoked  
additional concern  
Method Signature: int com.intellinuts.Operation.k()  
Result in advice: 3  
end of after returning advice...  
3 

If you see in the output, you can observe that the return value is printed two times, one by TrackOperation class and second by the Test class.

@Around Example

Just as its name suggests, the AspectJ around advice surrounds a joinpoint. Being one of the most powerful types of advice, around advice is applied before and after calling the actual business logic methods or method execution. It is denoted by @Around annotation. Using this advice, custom behavior can be done before and after the method invocation.

To better understand, let’s create a class named Operation.java in which actual business logic is presented.

package com.intellinuts;  
public class Operation{  
    public void msg(){System.out.println("msg() is invoked");}  
    public void display(){System.out.println("display() is invoked");}  
}

Now we will create the aspect class named TrackOperation.java that is presented with around advice:

Here, it is mandatory to pass the ProceedingJoinPoint reference in the advice method, so that the request is performed by calling the proceed() method.

package com.intellinuts;  
import org.aspectj.lang.ProceedingJoinPoint;  
import org.aspectj.lang.annotation.Around;  
import org.aspectj.lang.annotation.Aspect;  
import org.aspectj.lang.annotation.Pointcut;  

@Aspect  
public class TrackOperation  
{  
    @Pointcut("execution(* Operation.*(..))")  
    public void abcPointcut(){}  

    @Around("abcPointcut()")  
    public Object myadvice(ProceedingJoinPoint pjp) throws Throwable   
    {  
        System.out.println("Additional Concern Before calling actual method");  
        Object obj=pjp.proceed();  
        System.out.println("Additional Concern After calling actual method");  
        return obj;  
    }  
}  

Now we create the Test.java class that invokes the actual methods. This class will get the bean information from the Applicationcontext.xml file and display the output by calling the display() method.

package com.intellinuts;  
import org.springframework.context.ApplicationContext;  
import org.springframework.context.support.ClassPathXmlApplicationContext;  
public class Test{  
    public static void main(String[] args){  
        ApplicationContext context = new classPathXmlApplicationContext("applicationContext.xml");      

        Operation op = (Operation) context.getBean("opBean");  
        op.msg();  
        op.display();  
    }  
}  

Finally, the output will be displayed as:

Additional Concern Before calling actual method  
msg() is invoked  
Additional Concern After calling actual method  
Additional Concern Before calling actual method  
display() is invoked  
Additional Concern After calling actual method

As you can see in the output, an additional concern is printed before and after calling msg() and display() methods.

# Note that in this example, we will assume that the file Applicationcontext.xml is the same as in the @Before example.

@AfterThrowing Example

In Spring AOP, we can use after-throwing advice to ensure that the advice runs even if the method throws an exception. In other words, this advice will be executed if a join point fails to be completed normally and throws an exception.

In this example, we will use after-throwing advice denoted as @AfterThrowing, to print the exception in the TrackOperation class. Take a look at the example of AspectJ AfterThrowing advice:

First of all, we create an Operation.java class that is presented with business logic.

package com.intellinuts;  
public class Operation{  
    public void validate(int age)throws Exception{  
    if(age<18){  
        throw new ArithmeticException("Not valid age");  
    }  
    else{  
        System.out.println("Thanks for vote");  
    }  
    }  

}  

Now we will create the aspect class (in this example it is TrackOperation.java) that represents after throwing advice. Here an exception can be intercepted only by passing the Throwable reference.

package com.intellinuts;  
import org.aspectj.lang.JoinPoint;  
import org.aspectj.lang.annotation.AfterThrowing;  
import org.aspectj.lang.annotation.Aspect;  
@Aspect  
public class TrackOperation{  
    @AfterThrowing(  
              pointcut = "execution(* Operation.*(..))",  
              throwing= "error")  

    public void myadvice(JoinPoint jp,Throwable error)//it is advice  
    {  
        System.out.println("additional concern");  
        System.out.println("Method Signature: " + jp.getSignature());  
        System.out.println("Exception is: "+error);  
        System.out.println("end of after throwing advice...");  
    }  

}  

We will create the same applicationContext.xml file that we give in the @Before advice example.

In our next step, we will create a Test.java class that gets the bean information from the applicationContext.xml file and calls the actual methods.

package com.intellinuts;  
import org.springframework.context.ApplicationContext;  
import org.springframework.context.support.ClassPathXmlApplicationContext;  
public class Test{  
    public static void main(String[] args){ 
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");  
        Operation op = (Operation) context.getBean("opBean");  
        System.out.println("calling validate...");  
        try{  
            op.validate(19);  
        }catch(Exception e){System.out.println(e);}  
        System.out.println("calling validate again...");  

        try{  
            op.validate(11);  
        }catch(Exception e){System.out.println(e);}  
    }  

}  

The output of the above program says:

calling validate...  
Thanks for vote  
calling validate again...  
additional concern  
Method Signature: void com.intellinuts.Operation.validate(int)  
Exception is: java.lang.ArithmeticException: Not valid age  
end of after throwing advice...  
java.lang.ArithmeticException: Not valid age