-
Notifications
You must be signed in to change notification settings - Fork 49
Spring AOP AspectJ @Before, @After, @AfterReturning, @AfterThrowing and @Around Example
In this article, we will learn how to integrate AspectJ annotations with Spring AOP framework. We will create a simple spring boot application, add logging aspect and then invoke aspect methods based on pointcuts information passed in AspectJ annotations.
Common AspectJ annotations :
- @Before – Run before the method execution
- @After – Run after the method returned a result
- @AfterReturning – Run after the method returned a result, intercept the returned result as well.
- @AfterThrowing – Run after the method throws an exception
- @Around – Run around the method execution, combine all three advices above.
Let's first look at the snippets of each AspectJ annotations and then we will develop a complete example to demonstrate the usage of AspectJ @Before, @After, @AfterReturning, @AfterThrowing, and @Around annotations.
@Before annotated methods run exactly before all methods matching with pointcut expression. Here is a sample usage of @Before annotation:
@Aspect
@Component
public class LoggingAspect {
private final Logger log = LoggerFactory.getLogger(this.getClass());
/**
* Run before the method execution.
* @param joinPoint
*/
@Before("execution(* net.guides.springboot2.springboot2jpacrudexample.service.EmployeeService.addEmployee(..))")
public void logBefore(JoinPoint joinPoint) {
log.debug("logBefore running .....");
log.debug("Enter: {}() with argument[s] = {}", joinPoint.getSignature().getDeclaringTypeName(),
joinPoint.getSignature().getName(), Arrays.toString(joinPoint.getArgs()));
}
}- @Aspect - Indicates that this is an Aspect
- @Component - This annotation mark the beans as Spring’s managed components
- @Before annotated methods run exactly before all methods matching with pointcut expression
@After annotated methods run exactly after all methods matching with pointcut expression. You can use @After annotation in below manner.
@Aspect
@Component
public class LoggingAspect {
private final Logger log = LoggerFactory.getLogger(this.getClass());
/**
* Run after the method returned a result.
* @param joinPoint
*/
@After("execution(* net.guides.springboot2.springboot2jpacrudexample.service.EmployeeService.addEmployee(..))")
public void logAfter(JoinPoint joinPoint) {
log.debug("logAfter running .....");
log.debug("Enter: {}() with argument[s] = {}", joinPoint.getSignature().getDeclaringTypeName(),
joinPoint.getSignature().getName(), Arrays.toString(joinPoint.getArgs()));
}
}- @Aspect - Indicates that this is an Aspect
- @Component - This annotation mark the beans as Spring’s managed components
- @After annotated methods run exactly after all methods matching with pointcut expression
@Around annotated methods run before and after all methods matching with pointcut expression. Here is a sample usage of @Around annotation:
@Aspect
@Component
public class LoggingAspect {
private final Logger log = LoggerFactory.getLogger(this.getClass());
/**
* Run around the method execution.
* @param joinPoint
* @return
* @throws Throwable
*/
@Around("execution(* net.guides.springboot2.springboot2jpacrudexample.service.EmployeeService.getEmployeeById(..))")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
log.debug("logAround running .....");
if (log.isDebugEnabled()) {
log.debug("Enter: {}.{}() with argument[s] = {}", joinPoint.getSignature().getDeclaringTypeName(),
joinPoint.getSignature().getName(), Arrays.toString(joinPoint.getArgs()));
}
try {
Object result = joinPoint.proceed();
if (log.isDebugEnabled()) {
log.debug("Exit: {}.{}() with result = {}", joinPoint.getSignature().getDeclaringTypeName(),
joinPoint.getSignature().getName(), result);
}
return result;
} catch (IllegalArgumentException e) {
log.error("Illegal argument: {} in {}.{}()", Arrays.toString(joinPoint.getArgs()),
joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
throw e;
}
}
}- @Aspect - Indicates that this is an Aspect
- @Component - This annotation mark the beans as Spring’s managed components
- @Around annotated methods run before and after all methods matching with pointcut expression
Run after the method returned a result, intercept the returned result as well. Here is a usage of @AfterReturning annotation:
@Aspect
@Component
public class LoggingAspect {
private final Logger log = LoggerFactory.getLogger(this.getClass());
/**
* Run after the method returned a result, intercept the returned result as well.
* @param joinPoint
* @param result
*/
@AfterReturning(pointcut = "execution(* net.guides.springboot2.springboot2jpacrudexample.service.EmployeeService.deleteEmployee(..))", returning = "result")
public void logAfterReturning(JoinPoint joinPoint, Object result) {
log.debug("logAfterReturning running .....");
log.debug("Enter: {}() with argument[s] = {}", joinPoint.getSignature().getDeclaringTypeName(),
joinPoint.getSignature().getName(), Arrays.toString(joinPoint.getArgs()));
}
}- @Aspect - Indicates that this is an Aspect
- @Component - This annotation mark the beans as Spring’s managed components
- @AfterReturning - Run after the method returned a result, intercept the returned result as well
@AfterThrowing annotated methods run after the method (matching with pointcut expression) exits by throwing an exception. Here is a simple example:
@Aspect
@Component
public class LoggingAspect {
private final Logger log = LoggerFactory.getLogger(this.getClass());
/**
* Advice that logs methods throwing exceptions.
*
* @param joinPoint join point for advice
* @param e exception
*/
@AfterThrowing(pointcut = "execution(* net.guides.springboot2.springboot2jpacrudexample.service.EmployeeService.updateEmployee(..))", throwing = "error")
public void logAfterThrowing(JoinPoint joinPoint, Throwable error) {
log.debug("logAfterThrowing running .....");
log.error("Exception in {}.{}() with cause = {}", joinPoint.getSignature().getDeclaringTypeName(),
joinPoint.getSignature().getName(), error.getCause() != null ? error.getCause() : "NULL");
}
}- @Aspect - Indicates that this is an Aspect
- @Component - This annotation mark the beans as Spring’s managed components
- @AfterThrowing annotated methods run after the method (matching with pointcut expression) exits by throwing an exception.
package net.guides.springboot2.springboot2jpacrudexample.aspect;
import java.util.Arrays;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
/**
* Aspect for logging execution.
*
* @author Ramesh Fadatare
*
*/
@Aspect
@Component
public class LoggingAspect {
private final Logger log = LoggerFactory.getLogger(this.getClass());
/**
* Run before the method execution.
* @param joinPoint
*/
@Before("execution(* net.guides.springboot2.springboot2jpacrudexample.service.EmployeeService.addEmployee(..))")
public void logBefore(JoinPoint joinPoint) {
log.debug("logBefore running .....");
log.debug("Enter: {}() with argument[s] = {}", joinPoint.getSignature().getDeclaringTypeName(),
joinPoint.getSignature().getName(), Arrays.toString(joinPoint.getArgs()));
}
/**
* Run after the method returned a result.
* @param joinPoint
*/
@After("execution(* net.guides.springboot2.springboot2jpacrudexample.service.EmployeeService.addEmployee(..))")
public void logAfter(JoinPoint joinPoint) {
log.debug("logAfter running .....");
log.debug("Enter: {}() with argument[s] = {}", joinPoint.getSignature().getDeclaringTypeName(),
joinPoint.getSignature().getName(), Arrays.toString(joinPoint.getArgs()));
}
/**
* Run after the method returned a result, intercept the returned result as well.
* @param joinPoint
* @param result
*/
@AfterReturning(pointcut = "execution(* net.guides.springboot2.springboot2jpacrudexample.service.EmployeeService.deleteEmployee(..))", returning = "result")
public void logAfterReturning(JoinPoint joinPoint, Object result) {
log.debug("logAfterReturning running .....");
log.debug("Enter: {}() with argument[s] = {}", joinPoint.getSignature().getDeclaringTypeName(),
joinPoint.getSignature().getName(), Arrays.toString(joinPoint.getArgs()));
}
/**
* Run around the method execution.
* @param joinPoint
* @return
* @throws Throwable
*/
@Around("execution(* net.guides.springboot2.springboot2jpacrudexample.service.EmployeeService.getEmployeeById(..))")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
log.debug("logAround running .....");
if (log.isDebugEnabled()) {
log.debug("Enter: {}.{}() with argument[s] = {}", joinPoint.getSignature().getDeclaringTypeName(),
joinPoint.getSignature().getName(), Arrays.toString(joinPoint.getArgs()));
}
try {
Object result = joinPoint.proceed();
if (log.isDebugEnabled()) {
log.debug("Exit: {}.{}() with result = {}", joinPoint.getSignature().getDeclaringTypeName(),
joinPoint.getSignature().getName(), result);
}
return result;
} catch (IllegalArgumentException e) {
log.error("Illegal argument: {} in {}.{}()", Arrays.toString(joinPoint.getArgs()),
joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
throw e;
}
}
/**
* Advice that logs methods throwing exceptions.
*
* @param joinPoint join point for advice
* @param e exception
*/
@AfterThrowing(pointcut = "execution(* net.guides.springboot2.springboot2jpacrudexample.service.EmployeeService.updateEmployee(..))", throwing = "error")
public void logAfterThrowing(JoinPoint joinPoint, Throwable error) {
log.debug("logAfterThrowing running .....");
log.error("Exception in {}.{}() with cause = {}", joinPoint.getSignature().getDeclaringTypeName(),
joinPoint.getSignature().getName(), error.getCause() != null ? error.getCause() : "NULL");
}
}