Execute around Aspect with @annotation pointcut in Spring Boot

Aspect oriented programming (AOP) is a programming model where we write independently executable code which adds additional behavior to the existing code without modifying the existing code.

Wikipedia defines AOP as:

In this article, I will show you how to execute certain code around the execution of a method which means I would execute some code before the target method is called and some code after the target method has returned the value.

This extra code that executes around a target method is called an Aspect and when this code needs to be executed is called an Advice. There are different types of advice based on when we want our code to be executed:

  • before the target method
  • after the target method execution
  • around the target method execution
  • after throwing exception
  • always run irrespective of the method returned a value or failed due to exception.

Identifying the target method is done by writing an expression which we call a pointcut expression. There are different ways of identifying the target method:

  • based on the method names
  • based on the type/class where the method is defined
  • based on the return types, argument types
  • based on specific annotation to the method or
  • based on specific annotation to the arguments of the method

In this article, we will identify the methods to be enhanced using an annotation.

For a detailed explanation on AOP with Spring I would highly recommend you to read this documentation from Spring.

Updating Maven dependency

We will add the following dependency to our pom.xml for adding the required AOP libraries:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
Defining the Aspect
@Slf4j
@Aspect
@Component
public class TimerAspect {

    @Around("@annotation(Timer)")
    private Object recordTimeTaken(ProceedingJoinPoint pjp) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object value = pjp.proceed();
        long endTime = System.currentTimeMillis();
        log.debug("Time taken for method {} is {} ms", 
            pjp.toShortString(), (endTime - startTime));
        return value;
    }
}

Important parts in the above code:

  • Line 2: Declaring that this class is an aspect i.e has code which enhances target methods behavior. This is done by using @Aspect annotation
  • Line 3: Delcaring that this should be managed by Spring container by annotating with @Component so that the Spring container records this as a managed bean.
  • Line 6: This does two things:
    • Declares the type of advice which in our case is to execute around our target method. We declare the advice type by using @Around annotation.
    • To the advice we pass the pointcut expression to identify our target methods. In our case we will identify our target methods via @Timer annotation. So the pointcut expression we use is annotation(Timer).
  • Line 7: ProceedingJoinPoint is the method argument type for this kind of aspect.
  • Line 9: pjp.proceed() this invokes the target method execution and stores the result. This result is then returned from the aspect.
Defining the @Timer annotation

The new annotation we added @Timer is the key to identifying the target methods which need to be enhanced. The annotation is defined as:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Timer {
}
Enable AOP in Spring Boot

We will use the @EnableAspectJAutoProxy annotation to enable AOP support in our Spring Boot app.

Identifying the target methods

The methods which need to use the new aspect added will be annotated with @Timer annotation.

public class MyClass{
    @Timer
    public void myMethod(){
    }
}


Categories: Spring, Spring Boot

Tags: , , ,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: