Thursday, December 31, 2020

AOP with Spring Boot

 Learn to implement AOP in Spring Boot applications and add different aop advices using AspectJ to support cross-cutting concerns, such as logging, profiling, caching, and transaction management.

Table of Contents

1. Setting up AOP with Spring boot
2. Types of Advices
3. Conclusion

1. Setting up AOP with Spring boot

1.1. Maven

Setting up AOP in spring boot requires including spring-boot-starter-aop dependency. It imports spring-aop and aspectjweaver dependencies into the application. [Starter pom.xml]

pom.xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

1.2. Enable/disable auto configuration

Importing above dependencies triggers AopAutoConfiguration which enables AOP using @EnableAspectJAutoProxy annotation.

The auto configuration will NOT be activated if spring.aop.auto = false in application.properties.

application.properties
#spring.aop.auto = false    //'false' disables the auto configuration

1.3. Creating aspects with @Aspect

An aspect can be created in spring boot with help of annotations @Aspect annotation and registering with bean container with @Component annotation.

Inside the aspect class, we can create advices as required. For example, below class applies around advice on methods inside all classes in package com.howtodoinjava.aop. It captures the method start time and end time, and log the total method execution time in the log file.

LoggingAspect.java
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;
 
@Aspect
@Component
public class LoggingAspect
{
    private static final Logger LOGGER = LogManager.getLogger(LoggingAspect.class);
     
    @Around("execution(* com.howtodoinjava.aop..*(..)))")
    public Object profileAllMethods(ProceedingJoinPoint proceedingJoinPoint) throws Throwable
    {
        MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
          
        //Get intercepted method details
        String className = methodSignature.getDeclaringType().getSimpleName();
        String methodName = methodSignature.getName();
          
        final StopWatch stopWatch = new StopWatch();
          
        //Measure method execution time
        stopWatch.start();
        Object result = proceedingJoinPoint.proceed();
        stopWatch.stop();
  
        //Log method execution time
        LOGGER.info("Execution time of " + className + "." + methodName + " "
                            + ":: " + stopWatch.getTotalTimeMillis() + " ms");
  
        return result;
    }
}

1.4. Spring boot AOP Example

Create a simple service class to test the above advice.

DomainService.java
@Service
public class DomainService
{
    public Object getDomainObjectById(Long id)
    {
        try {
            Thread.sleep(new Random().nextInt(2000));
        } catch (InterruptedException e) {
            //do some logging
        }
        return id;
    }
}

Create a test class and execute the given method and watch out the logs.

AopSpringBootTest.java
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
 
@RunWith(SpringRunner.class)
@SpringBootTest
public class AopSpringBootTest
{
    @Autowired
    private DomainService service;
     
    @Test
    public void testGetDomainObjectById()
    {
        service.getDomainObjectById(10L);
    }
}
Console
2019-11-07T21:02:58.390+0530 INFO Execution time of DomainService.getDomainObjectById :: 1145 ms

As we can see that AOP advice has been applied over the service method.

2. Types of Advices

There are five types of advice in aspectj AOP.

  1. @Before : Advice that executes before a join point, but which does not have the ability to prevent execution flow proceeding to the join point (unless it throws an exception).
  2. @AfterReturning : Advice to be executed after a join point completes normally.
  3. @AfterThrowing : Advice to be executed if a method exits by throwing an exception.
  4. @After : Advice to be executed regardless of the means by which a join point exits (normal or exceptional return).
  5. @Around : Advice that surrounds a join point such as a method invocation.

3. Conclusion

Implementing AOP with Spring boot requires very little effort and we are ready to add aspects as soon as we add spring-boot-starter-aop dependency.

We anytime we want to disable aop auto-configuration, we can easily do by switching to spring.aop.auto to false.

Creating aspects and advices is as simple as adding some annotations e.g. @Aspect@Around etc.

Happy Learning !!

No comments:

Post a Comment

How to DROP SEQUENCE in Oracle?

  Oracle  DROP SEQUENCE   overview The  DROP SEQUENCE  the statement allows you to remove a sequence from the database. Here is the basic sy...