English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Spring AOP AspectJ annotation example

Spring frameworkIt is recommended that you use it on the Spring-based 1.2Used on the old-style dtd AOP implementation Spring AspectJ AOP implementationEasy to use.

There are two ways to use the Spring AOP AspectJ implementation:

Through annotations: We will learn it here. Through xml configuration (based on pattern): We will learn it on the next page.

Note: To understand the concepts of AOP and its advantages, please visit here. AOP Concept Tutorial

Spring AspectJ AOP implementation provides many annotations:

@Aspect Declare this class as a concern. @Pointcut Declare the pointcut expression.

The annotations used to create advice are as follows:

@Before Declared before advice. It is applied before the actual method is called. @After Declared after advice. It is applied after the actual method is called and before the result is returned. @AfterReturning Declared after advice. It is applied after the actual method is called and before the result is returned. However, you can get the result value in the advice. @Around Declared around advice. It is applied before and after the actual method is called. @AfterThrowing Declared throws advice. This method is applied if the actual method throws an exception.

Understanding pointcut

Pointcut is a language expression of Spring AOP.

@Pointcut Comments are used to define pointcuts. We can also refer to pointcut expressions by name. Let's look at a simple example of a pointcut expression.

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

The name of the pointcut expression is doSomething(). It will be applied to all methods of the Operation class regardless of the return type.

Understanding the pointcut expression

Let's try to understand the pointcut expression through the following example:

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

It will be applied to all public methods.


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

It will be applied to all public methods of the Operation class.


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

It will be applied to all methods of the Operation class.


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

It will be applied to all public setter methods of the Employee class.


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

It will be applied to all method of the Operation class that returns an int value.


1、@Before example

Apply AspectJ Before Advice before the actual business logic method. You can perform any operation here, such as transformation, authentication, etc.

Create a class that contains the actual business logic.

File: Operation.java

package com.w;3codebox;
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, create the aspect class that is included before the advice.

File: TrackOperation.java

package com.w;3codebox;
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()")//Apply the pointcut on the before notification
	public void myadvice(JoinPoint jp)//it is advice (before advice)
	{
		System.out.println("additional concern");
		//System.out.println("Method Signature: "}  + jp.getSignature());
	{}
{}

Now, create the applicationContext.xml file that defines the bean.

File: 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.w3codebox.Operation">	</bean>
	<bean id="trackMyBean" class="com.w3codebox.TrackOperation"></bean>
	<bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"></bean>
</beans>

Now, let's call it the actual method.

File: Test.java

package com.w;3codebox;
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();
	{}
{}

Output

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

As you can see, other issues appear before calling the msg(), m() and k() methods.

Now, if you change the切入点 expression as follows:

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

Now, we will pay more attention to the methods starting with m in the Operation class. The output will be as follows:

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

Now you can see that no other issues are printed before calling the k() method.


2Example of @After

After the actual business logic method is called, AspectJ is applied after the after advice. It can be used for maintaining logs, security, notifications, etc.

In this case, we assume Operation.java , applicationContext.xml and Test.java The file is the same as the one given in the @Before example.

File: TrackOperation.java
package com.w;3codebox;
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());
	{}
{}
 

Output

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

You can see that after calling the msg(), m() and k() methods, other issues also appear.


3Example of @AfterReturning

By using it after the return advice, we can obtain the result in the advice.

Create the class business logic containing the following content.

File: Operation.java

package com.w;3codebox;
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;}
{}
 

Create the aspect class containing the advice after the return.

File: TrackOperation.java

package com.w;3codebox;
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...");
	{}
{}
 

File: applicationContext.xml

as given in the @Before advice example.

File: Test.java

Now create the Test class that calls the actual method.

package com.w;3codebox;
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());
	{}
{}
 

Output

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

You can see that the return value is printed twice, once by the TrackOperation class and the second time by the Test class.


4, @Around example

The AspectJ around the notification is applied before and after the actual business logic method is called.

Here, we are assuming   applicationContext.xml The file is the same as the one given in the @Before example.

Create a class that contains the actual business logic.

File: Operation.java

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

Create a class that contains the aspect around the advice.

You need to pass in the advice method   PreceedingJoinPoint Reference, so that we can call the request() method through the proce.

File: TrackOperation.java

package com.w;3codebox;
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;
	{}
{}
 

File: Test.java

Now create the Test class that calls the actual method.

package com.w;3codebox;
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();
	{}
{}
 

Output

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
 

You can see that other issues are also printed before and after calling msg() and the display method.


5Example of @AfterThrowing

By using the after throw advice, we can print exceptions in the TrackOperation class. Let's look at an example of the AspectJ AfterThrowing advice.

Create a class containing business logic.

File: Operation.java

package com.w;3codebox;
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");
	{}
	{}
{}
 

Create an aspect class that includes after throwing advice.

Here, we also need to pass a Throwable reference so that we can intercept exceptions here.

File: TrackOperation.java

package com.w;3codebox;
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...");
	{}
{}
 

File: applicationContext.xml

as given in the @Before advice example.

File: Test.java

Now create the Test class that calls the actual method.

package com.w;3codebox;
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);}
	{}
{}
 

Output

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