In this Spring AOP example, we will learn to use AspectJ @After annotation in Spring-based applications. After advice methods annotated with @After that will execute after a join point execution, no matter how the execution ended.
In this example, We will create a simple spring boot application, add logging aspect and then invoke aspect methods based on pointcuts information passed in a @After annotation.
Below snippet shows usage of @After annotation:
package net.guides.springboot2.springaop.aspect; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; @Aspect @Component public class LoggingAspect { private final Logger LOGGER = LoggerFactory.getLogger(this.getClass()); @After("execution(* net.guides.springboot2.springaop.service.EmployeeService.*(..))") public void logAfterAllMethods(JoinPoint joinPoint) { LOGGER.debug("****LoggingAspect.logAfterAllMethods() : " + joinPoint.getSignature().getName()); } @After("execution(* net.guides.springboot2.springaop.service.EmployeeService.getEmployeeById(..))") public void logAfterGetEmployee(JoinPoint joinPoint) { LOGGER.debug("****LoggingAspect.logAfterGetEmployee() : " + joinPoint.getSignature().getName()); } @After("execution(* net.guides.springboot2.springaop.service.EmployeeService.addEmployee(..))") public void logAfterAddEmployee(JoinPoint joinPoint) { LOGGER.debug("****LoggingAspect.logAfterCreateEmployee() : " + joinPoint.getSignature().getName()); } @After("execution(* net.guides.springboot2.springaop.service.EmployeeService.deleteEmployee(..))") public void logAfterDeleteEmployee(JoinPoint joinPoint) { LOGGER.debug("****LoggingAspect.logAfterCreateEmployee() : " + joinPoint.getSignature().getName()); } @After("execution(* net.guides.springboot2.springaop.service.EmployeeService.getAllEmployees(..))") public void logAfterGetAllEmployees(JoinPoint joinPoint) { LOGGER.debug("****LoggingAspect.logAfterCreateEmployee() : " + joinPoint.getSignature().getName()); } }
Let's demonstrate the usage of @After annotation with a complete step by step example.
There are many ways to create a Spring Boot application. You can refer below articles to create a Spring Boot application.
>> Create Spring Boot Project With Spring Initializer
>> Create Spring Boot Project in Spring Tool Suite [STS]
Refer next step to create a project packaging structure.
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>net.guides.springboot2</groupId> <artifactId>springboot2-springaop-example</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>springboot2-springaop-example</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.0.4</version> <relativePath /> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>17</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
Below project structure for your reference -
package net.guides.springboot2.springaop.aspect; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; @Aspect @Component public class LoggingAspect { private final Logger LOGGER = LoggerFactory.getLogger(this.getClass()); @After("execution(* net.guides.springboot2.springaop.service.EmployeeService.*(..))") public void logAfterAllMethods(JoinPoint joinPoint) { LOGGER.debug("****LoggingAspect.logAfterAllMethods() : " + joinPoint.getSignature().getName()); } @After("execution(* net.guides.springboot2.springaop.service.EmployeeService.getEmployeeById(..))") public void logAfterGetEmployee(JoinPoint joinPoint) { LOGGER.debug("****LoggingAspect.logAfterGetEmployee() : " + joinPoint.getSignature().getName()); } @After("execution(* net.guides.springboot2.springaop.service.EmployeeService.addEmployee(..))") public void logAfterAddEmployee(JoinPoint joinPoint) { LOGGER.debug("****LoggingAspect.logAfterCreateEmployee() : " + joinPoint.getSignature().getName()); } @After("execution(* net.guides.springboot2.springaop.service.EmployeeService.deleteEmployee(..))") public void logAfterDeleteEmployee(JoinPoint joinPoint) { LOGGER.debug("****LoggingAspect.logAfterCreateEmployee() : " + joinPoint.getSignature().getName()); } @After("execution(* net.guides.springboot2.springaop.service.EmployeeService.getAllEmployees(..))") public void logAfterGetAllEmployees(JoinPoint joinPoint) { LOGGER.debug("****LoggingAspect.logAfterCreateEmployee() : " + joinPoint.getSignature().getName()); } }
package net.guides.springboot2.springaop.model; public class Employee { private long id; private String firstName; private String lastName; private String emailId; public Employee() { } public Employee(long id, String firstName, String lastName, String emailId) { this.id = id; this.firstName = firstName; this.lastName = lastName; this.emailId = emailId; } public long getId() { return id; } public void setId(long id) { this.id = id; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getEmailId() { return emailId; } public void setEmailId(String emailId) { this.emailId = emailId; } @Override public String toString() { return "Employee [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + ", emailId=" + emailId + "]"; } }
Let's create a few service methods for Employee on which aspects need to be executed.
package net.guides.springboot2.springaop.service; import java.util.ArrayList; import java.util.List; import org.springframework.stereotype.Service; import net.guides.springboot2.springaop.model.Employee; @Service public class EmployeeService { private List < Employee > employees = new ArrayList < > (); public List < Employee > getAllEmployees() { System.out.println("Method getAllEmployees() called"); return employees; } public Employee getEmployeeById(Long employeeId) { System.out.println("Method getEmployeeById() called"); for (Employee employee: employees) { if (employee.getId() == Long.valueOf(employeeId)) { return employee; } } return null; } public void addEmployee(Employee employee) { System.out.println("Method addEmployee() called"); employees.add(employee); } public void updateEmployee(Employee employeeDetails) { System.out.println("Method updateEmployee() called"); for (Employee employee: employees) { if (employee.getId() == Long.valueOf(employeeDetails.getId())) { employees.remove(employee); employees.add(employeeDetails); } } } public void deleteEmployee(Long employeeId) { System.out.println("Method deleteEmployee() called"); for (Employee employee: employees) { if (employee.getId() == Long.valueOf(employeeId)) { employees.remove(employee); } } } }
Now let’s test whether the above-configured aspects execute on given pointcut information using Spring boot Application:
package net.guides.springboot2.springaop; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ApplicationContext; import net.guides.springboot2.springaop.model.Employee; import net.guides.springboot2.springaop.service.EmployeeService; @SpringBootApplication public class Application { public static void main(String[] args) { ApplicationContext applicationContext = SpringApplication.run(Application.class, args); EmployeeService employeeService = applicationContext.getBean(EmployeeService.class); employeeService.addEmployee(new Employee(100 L, "ramesh", "fadatare", "ramesh@gmail.com")); employeeService.getEmployeeById(100 L); employeeService.getAllEmployees(); } }
Output:
From the above diagram, it clears that aspect advice executed on relevant joinpoints.
To learn more about Spring AOP then check out the complete Spring AOP Tutorial.