Spring AOP + @AspectJ Annotation Example

By Arvind Rai, March 09, 2023
This page will walk through Spring AOP and @AspectJ annotation example with @Aspect, @Pointcut, @Before, @After, @Around, @AfterReturning, @AfterThrowing annotations. AOP stands for Aspect Oriented Programming. The @AspectJ is a style to declare aspects in a Java class using annotations. To enable @AspectJ, Spring AOP provides @EnableAspectJAutoProxy annotation which will be annotated in Java configuration class. To work with Spring AOP and @AspectJ support, we need to create a class annotated with @Aspect annotation. In this class we have to create our pointcut and using pointcut we need to create our advice. Spring AOP is used for different purposes such as logging, handling with exception and validating return value of a method.
Here on this page we will provide a complete example to work with Spring AOP and @AspectJ support using annotation.

1. Technologies Used

Find the technologies being used in our example.
1. Java
2. Spring
3. Eclipse
4. Gradle

2. AOP Terminology

We should know the AOP terminology to work with it.

Aspect: Aspect is crosscutting concern. One aspect can lie in multiple objects.
Join point: Join point is a point that represents the execution of a method.
Advice: Advice is an action taken by aspect.
Pointcut: A scenario which matches to join point.
Target object: If an object is advised by more than one aspect, that object is called target object. This is also referred as advised object.
Weaving: Linking aspects to other application objects to create an advised object.

3. Project Structure in Eclipse

Find the project structure in eclipse.
Spring AOP + @AspectJ Annotation Example

4. Gradle Dependencies

Find the Gradle file to resolve JAR dependencies.
build.gradle
dependencies {
    compile 'org.springframework.boot:spring-boot-starter-aop:1.2.7.RELEASE'
    compile 'org.springframework:spring-aspects:4.1.8.RELEASE'
} 

5. Configure @EnableAspectJAutoProxy

In java configuration to support @AspectJ, spring provides @EnableAspectJAutoProxy annotation. We use it as follows.
AspectConfig.java
package com.concretepage;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@EnableAspectJAutoProxy
@ComponentScan(basePackages="com.concretepage")
public class AspectConfig {
}  

6. @Aspect Annotation

To create aspect, we need to use @Aspect annotation at class level. This class will consist all advices. The sample aspect class will look as follows.
@Aspect
public class TimeLoggingAspect {
}  

7. @Pointcut Annotation

To define @Pointcut annotation, we need to take help of expression. Pointcut is to determine join points of interest. Find some sample poincuts.
1. If we need to apply our advice to all classes of the package com.concretepage.service, do as follows.
 @Pointcut(" execution(* com.concretepage.service.*.*(..))")
  
2. To apply advice only for a method of a class, write expression as follows.
@Pointcut(" execution (* com.concretepage.bean.UserService.doTask(..))")
 
3. The below pointcut expression will allow the advice to be used by all the methods of UserService class.
@Pointcut(" execution(* com.concretepage.bean.UserService+.*(..))")
 
The advice can use pointcut in different way. Define the pointcut annotated on a method and that method will be used by advice like @After annotation. The method serving as a pointcut expression must have void return type.
@Pointcut(" execution (* com.concretepage.bean.UserService.doTask(..))")
public void pointcutDemo() {}
@After("pointcutDemo())")
public void logdvice(){ } 
The advice can use pointcut directly as an attribute with other attributes.
@AfterThrowing(pointcut = "execution(* com.concretepage.service.*.*(..))",
			throwing="exception")
public void logAfterThrowing(Exception exception){} 
If advice consists only pointcut as an attribute, we can directly write pointcut expression in advice.
@Before("execution(* com.concretepage.service.*.*(..))")
public void logBefore(){} 

8. @Before Advice

@Before annotation is used to create before advice. We need to create a method in the aspect class annotated with @Before and define that method. We defined pointcut with @Before annotation. The sample use of before advice can be logging before running the method.
TimeLoggingAspect.java
package com.concretepage.aspect;
import java.util.Date;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class TimeLoggingAspect {
	@Before("execution(* com.concretepage.service.*.*(..))")
	public void logBefore(){
		System.out.println("@Before:"+new Date());
	}
}  
Find the service class.
UserService.java
package com.concretepage.service;
import org.springframework.stereotype.Service;
@Service
public class UserService {
	public Integer multiply(int a, int b){
		int res = a*b;
		System.out.println(a+ "*" + b +"= " + res);
		return res;
	}
}  
To test the application, find the class with Main method.
SpringAOPTest.java
package com.concretepage;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.concretepage.service.UserService;
public class SpringAOPTest {
   public static void main(String[] args) {
       AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
       ctx.register(AspectConfig.class);
       ctx.refresh();
       UserService userService = ctx.getBean(UserService.class);
       userService.multiply(2, 3);
   }
}  
Find the output.
@Before:Tue Dec 15 17:28:38 IST 2015
2*3= 6  

9. @After Advice

@After advice runs just after a method completes it process. It is declared same as @Before annotation. We need to create a method annotated with @After in aspect class.
TimeLoggingAspect.java
package com.concretepage.aspect;
import java.util.Date;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class TimeLoggingAspect {
	@After("execution(* com.concretepage.service.*.*(..))")
	public void logAfter(){
		System.out.println("@After:"+new Date());
	}
} 
Run SpringAOPTest and find the output.
2*3= 6
@After:Wed Dec 16 17:49:54 IST 2015  


10. @Around Advice with ProceedingJoinPoint.proceed()

Using @Around annotation, we can achieve the functionality of both @Before and @After advice. For this we need to create a method annotated with @Around in aspect class. Inside this method use ProceedingJoinPoint.proceed() and before and after of this line, write your advice like logging.
TimeLoggingAspect.java
package com.concretepage.aspect;
import java.util.Date;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class TimeLoggingAspect {
	@Around("execution(* com.concretepage.service.*.*(..))")
	public void userAdvice(ProceedingJoinPoint joinPoint) throws Throwable{
		System.out.println("@Around: Before calculation-"+ new Date());
		joinPoint.proceed();
		System.out.println("@Around: After calculation-"+ new Date());
	}
}  
Find the output.
@Around: Before calculation-Thu Dec 17 11:47:20 IST 2015
2*3= 6
@Around: After calculation-Thu Dec 17 11:47:20 IST 2015  

11. @AfterReturning Advice

@AfterReturning annotation is used to create after returning advice. @AfterReturning has attribute as returning which can be used to get retuned data from a method which is covered by defined pointcut with @AfterReturning annotation.
TimeLoggingAspect.java
package com.concretepage.aspect;
import java.util.Date;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class TimeLoggingAspect {
	@AfterReturning(pointcut = "execution(* com.concretepage.service.*.*(..))",
			returning="val")
	public void logAfterReturning(Object val){
		System.out.println("Method return value:"+ val);
		System.out.println("@AfterReturning:"+new Date());
	}
}  
Find the output.
2*3= 6
Method return value:6
@AfterReturning:Wed Dec 16 20:58:41 IST 2015  

12. @AfterThrowing Advice

Using AOP we can also create an advice which will run just after throwing any exception. For this we need to use @AfterThrowing annotation to define our advice in aspect class. To work with exception, @AfterThrowing has an attribute as throwing.
TimeLoggingAspect.java
package com.concretepage.aspect;
import java.util.Date;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class TimeLoggingAspect {
	@AfterThrowing(pointcut = "execution(* com.concretepage.service.*.*(..))",
			throwing="exception")
	public void logAfterThrowing(Exception exception){
		System.out.println("@AfterReturning:"+new Date());
		System.out.println("Exception caught:"+ exception.getMessage());
	}
}  
Find the UserService, in which we are dividing a number by another number.
UserService.java
package com.concretepage.service;
import org.springframework.stereotype.Service;
@Service
public class UserService {
	public Integer devide(int a, int b){
		int res = a/b;
		System.out.println(a+ "/" + b +"= " + res);
		return res;
	}
}  
To throw the exception, we will use zero divisor. In SpringAOPTest, we need to use below line.
UserService userService = ctx.getBean(UserService.class);
userService.devide(5,0);  
What we will observe that the exception will be caught by @AfterThrowing. Find the output.
@AfterReturning:Thu Dec 17 11:31:32 IST 2015
Exception caught:/ by zero
Exception in thread "main" java.lang.ArithmeticException: / by zero
	at com.concretepage.service.UserService.devide(UserService.java:6)  

13. Reference

14. Download Source Code

POSTED BY
ARVIND RAI
ARVIND RAI
LEARN MORE








©2024 concretepage.com | Privacy Policy | Contact Us