spring boot

Spring Boot AOP Example

An introduction to Spring Boot Aspect Oriented Programming and how to use it with simple example AOP implementation.

We can use AOP aspects to intercept the program flow execution and perform additional functionalities along with actual functionalities. We can use AOP aspects for security, logging, etc. Spring Boot also provides good support for AOP by providing the spring-boot-starter-aop dependency. In this article, We will learn about simple spring boot logging AOP implementation examples.

We will implement a simple Logging aspect that intercepts the service and controller class method flow. We will also learn how to use point-cut expressions and different aspect types supported by the AspectJ framework.

Version Details:

  • Spring boot version 2.7.1
  • JDK version 18

Table of Contents

Creating Spring Boot application

Create a spring boot application with the below dependencies.

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
	<groupId>org.projectlombok</groupId>
	<artifactId>lombok</artifactId>
	<optional>true</optional>
</dependency>

We are creating a REST API that returns a greeting message. For this, we are using spring-boot-starter-web dependency. The spring-boot-starter-aop is the spring boot starter dependency that provides the required support for implementing AOP.

Also, We are using the Lombok maven dependency to reduce the boilerplate code.

Adding the application logic

Create a simple service class with the name GreetingService as shown below.

@Slf4j
@Service
public class GreetingService {
    public String getGreeting(String name){
        log.info("Returning greeting message from service..");
        return "Hello " + name;
    }
}

Create a simple Rest Controller class with the name GreetingController as shown below.

@RestController
public class GreetingController {

    @Autowired
    private GreetingService greetingService;

    @GetMapping("/")
    public String getGreeting(@RequestParam("name") String name){
        return greetingService.getGreeting(name);
    }
}

Run the application. We should be able to see the application logs from the service class, as shown below, along with the greeting message.

spring boot aop example
INFO 313642 --- [nio-8080-exec-2] com.asbnotebook.service.GreetingService  : Returning greeting message from service..

Implementing Spring Boot logging AOP example

Let’s add the logging aspect to the service method that we created earlier. We will use the Around aspect to print the details about the method before and after the method invocation.

Creating a simple logging aspect

Create a Logging aspect class with the name LoggingAspect and add the below content.

@Slf4j
@Aspect
@Component
public class LoggingAspect {

    @Around("execution(* com.asbnotebook.service.*.*(..))")
    public Object logServiceMethods(ProceedingJoinPoint joinPoint) throws Throwable {
        Object[] params = joinPoint.getArgs();
        String methodName = joinPoint.getSignature().getName();

        log.info("Entering into service:{} with params: {}",methodName, params);
        Object result = joinPoint.proceed();
        log.info("Returning from service method:{} with response: {}", methodName, result);

        return result;
    }
}

Here, we have annotated the class with @Aspect annotation. Adding this makes it an aspect class. Also, with the help of @Component, the bean is created and added to the spring application context.

We have created a logServiceMethods method, annotated with @Around annotation. The Around advice is one of the supported AOP advice. With the help of the Around advice, spring decides when to intercept the incoming requests.

We are printing the incoming parameter values of the service method along with the method name.

The ProceedingJoinPoint object helps us retrieve the name and parameters of the method that the aspect method is intercepting, the method return value, etc.

Also, after the method invocation is complete, we log the method’s return value.

Point cut expression

We have also specified a pointcut expression along with the @Around advice. The point cut expressions decide the exact point(or method) of the code execution it should intercept.

Advertisements
execution(* com.asbnotebook.service.*.*(..))

The point-cut expression above says intercept all the methods under the package com.asbnotebook.service. The first * mentions that the method may have any return type.

Finally, the next two * symbols is to conveys that apply the aspect logic for all methods of service classes under the package and method can have any type/number of parameters.

Enabling the AOP

We also need to add the @EnableAspectJAutoproxy annotation to enable the AOP.

@SpringBootApplication
@EnableAspectJAutoProxy
public class AopApplication {
	public static void main(String[] args) {
		SpringApplication.run(AopApplication.class, args);
	}
}

Below is the output of the above code. We can observe that the application invokes the logging aspect before and after the invocation of the service method.

INFO 313642 --- [nio-8080-exec-2] com.asbnotebook.aspect.LoggingAspect     : Entering into service:getGreeting with params: [arun]
INFO 313642 --- [nio-8080-exec-2] com.asbnotebook.service.GreetingService  : Returning greeting message from service..
INFO 313642 --- [nio-8080-exec-2] com.asbnotebook.aspect.LoggingAspect     : Returning from service method:getGreeting with response: Hello arun

Implementing annotation based AOP

We can also create a convenient custom annotation and make use of the annotation to apply the aspect.

Creating custom annotation

Create a custom annotation interface as shown below.

Here, we can apply the annotation at the method level.

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface LogIt {
}

Adding the logging AOP method

Add a new AOP method ad shown below.

Here, we will use the @Before aspect logs the message just before the invocation of the method.

@Slf4j
@Aspect
@Component
public class LoggingAspect {

    @Around("execution(* com.asbnotebook.service.*.*(..))")
    public Object logServiceMethods(ProceedingJoinPoint joinPoint) throws Throwable {
        Object[] params = joinPoint.getArgs();
        String methodName = joinPoint.getSignature().getName();

        log.info("Entering into service:{} with params: {}",methodName, params);
        Object result = joinPoint.proceed();
        log.info("Returning from service method:{} with response: {}", methodName, result);

        return result;
    }

    @Before("@annotation(LogIt)")
    public void logWithAnnotation(JoinPoint joinPoint){
        log.info("Before entering the method:{} with params:{}", joinPoint.getSignature().getName(), joinPoint.getArgs());
    }
}

Applying the AOP annotation

Now our annotation-based logging aspect is ready, and let’s apply it to our controller method.

@RestController
public class GreetingController {
    @Autowired
    private GreetingService greetingService;

    @LogIt
    @GetMapping("/")
    public String getGreeting(@RequestParam("name") String name){
        return greetingService.getGreeting(name);
    }
}

Finally, it’s time to run the application and now we should be able to see our new aspect in action.

INFO 315853 --- [nio-8080-exec-2] com.asbnotebook.aspect.LoggingAspect     : Before entering the method:getGreeting with params:[arun]
INFO 315853 --- [nio-8080-exec-2] com.asbnotebook.aspect.LoggingAspect     : Entering into service:getGreeting with params: [arun]
INFO 315853 --- [nio-8080-exec-2] com.asbnotebook.service.GreetingService  : Returning greeting message from service..
INFO 315853 --- [nio-8080-exec-2] com.asbnotebook.aspect.LoggingAspect     : Returning from service method:getGreeting with response: Hello arun

Different AOP aspects supported by AspectJ framework

In the above example, we used the @Around and @Before AOP aspects.

Similarly, there are other AOP aspects also that we can leverage. A few of them are below.

  • @AfterReturning: Invokes the aspect logic after executing the intercepted method. If the intercepted method throws any exception, skips the aspect logic execution.
  • @AfterThrowing: Invokes the aspect logic in case of exception event occurs on an intercepted method execution.
  • @After: The aspect calls the aspect logic after executing the intercepted method. This aspect is called even if an exception is thrown in the intercepted method.

Conclusion

In this article, We learned about a simple example implementation of the spring boot logging AOP application.

We also learned how to use join point and AOP aspects by implementing a simple logging aspect.

The example code is available on GitHub.

Leave a Reply