Aspect-oriented programming (AOP) with Spring Boot

Aspect-oriented programming (AOP) with Spring Boot

Overview

Aspect-oriented programming (AOP) is a programming paradigm that aims to increase modularity by allowing the separation of cross-cutting concerns. Crosscutting concerns are parts of a program that rely on or must affect many other parts of the system. Commonly used cross-cutting concerns are:

  • logging
  • transaction management
  • performance monitoring
  • security checks
  • etc.

AOP concepts

Aspect: The concern that cuts across multiple classes or modules. Transaction and security are examples. Spring Transaction is implemented as Aspects.

Join point: A point during the execution of the program at which you want to insert additional logic using AOP. A method execution and class instantiation are examples.

Advice: The action taken by the Aspect at a particular join point. There are different types: before, after and around.

Pointcut: An expression that defines or matches a set of join points. The Advice associated with a pointcut executes at any join point it matches. Spring supports the AspectJ pointcut expression language by default. An example is execution(*com.keepcodeclean.service..(..))

Target object: object being advised by one or more aspects. Also referred to as the advised object. Since Spring AOP is implemented using runtime proxies, this object will always be a proxied object.

AOP proxy: an object created by the AOP framework in order to implement the aspect contracts (advise method executions and so on). In the Spring Framework, an AOP proxy will be a JDK dynamic proxy or a CGLIB proxy.

Spring AOP Maven dependency

The following dependency has to be added to enable AOP in Spring Boot:

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

Application

The best way to learn something is to try it yourself, so let’s create a simple application which uses AOP for performance monitoring.

At first, we need to create a service that represents a business logic whose performance is going to be monitored.

@Service
public class BusinessLogicService {

    public void processSmth() throws InterruptedException {
        Thread.sleep(1500);
    }
    
}

To measure the performance of a processSmth method, a corresponding annotation will be added. So, let’s create it:

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

This annotation has to be added to processSmth method in BusinessLogicService.

Now an Aspect can be created:

@Aspect
@Component
public class PerformanceMonitoringAspect {
    @Around("@annotation(com.keepcodeclean.aop.annotation.MonitorPerformance)")
    public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();

        Object proceed = joinPoint.proceed();

        long executionTime = System.currentTimeMillis() - start;

        System.out.println(joinPoint.getSignature() + " executed in " + executionTime + " ms");
        
        return proceed;
    }
    
}

As we can see from the code, PerformanceMonitoringAspect represents an Aspect for performance monitoring of methods.

Join point is a method execution.

@Around advice surrounds a joinpoint such as a method invocation. Around advice can perform custom behavior before and after the method invocation. It is also responsible for choosing whether to proceed to the join point or to shortcut the advised method execution by returning its own return value or throwing an exception.

Pointcut is “@annotation(com.keepcodeclean.aop.annotation.MonitorPerformance)”. It means that the logExecutionTime will be called for all methods annotated with @MonitorPerformance.
Pointcuts are flexible. If we don’t want to put annotations for every method we could use the following pointcut to cover all methods executions under service package:

"execution(* com.keepcodeclean.aop.service..*.*(..))"

Additionally, access modifiers (e.g. public), return types, method parameters could be specified. Annotations require code changes, while a pointcut can be changed in XML configuration that allows not to rebuild the application package.

Let’s run the following application:

@SpringBootApplication
public class AopTutorialApplication implements CommandLineRunner {

	@Autowired
	private BusinessLogicService businessLogicService;
	
	public static void main(String[] args) {
		SpringApplication.run(AopTutorialApplication.class, args);
	}

	@Override
	public void run(String... args) throws Exception {
		businessLogicService.processSmth();
	}
}
void com.keepcodeclean.aop.service.BusinessLogicService.processSmth() executed in 1508 ms

So, we’ve learned on this basic example how to use Aspect-oriented programming (AOP) with Spring Boot. From now on, you should be able to adjust it for your needs.

One thought on “Aspect-oriented programming (AOP) with Spring Boot

Leave a Reply

Your email address will not be published. Required fields are marked *