What is Spring Aspect Oriented Programming?

I have to admit that AOP and all the concepts behind it are not easy to catch at the beginning. After reading some definitions about Spring-aop and looking examples, I found a good and simple definition that I’d like to share:

“Spring AOP (Aspect-oriented programming) framework is used to modularize cross-cutting concerns in aspects. Put it simple, it’s just an interceptor to intercept some processes, for example, when a method is executed, Spring AOP can hijack the executing method, and add extra functionality before or after the method execution” https://mkyong.com/spring/spring-aop-examples-advice/.

Examples that are mentioned in many sites are related to logging and verification and in most cases are temporal or have a cross-cutting concern, it means a same code that needs to be used in many places (temporal or not) could be hijacked without changing the original code.

How can I use it?

Well to start simple, we can create a custom annotation and then use AOP to understand how it works.

Dependencies

In this example, I’m using Spring Boot and the AOP starter that pulls the libraries required to implement with Aspects.

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.12.RELEASE</version>
</parent>

<dependencies>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
</dependencies>

Custom Annotation

I’m creating an annotation where I define that it only can be used by methods, and it will be available to the JVM at runtime.

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

}

Example Service Component

Now, let’s create a component with a fake slow method and then include our annotation, until now we don’t have any Aspect configured yet.

@Component
public class ExampleService {

    @LogElapsedTime
    public void simulateSlowMethod() throws InterruptedException {
        Thread.sleep((int)(Math.random() * 1000));
    }
}

Example Aspect Component

Let’s create another component and in this case annotate also with @Aspect. In this component we need to create the pointcut and advice. I defined the advice to be @Around, it means I’m including extra code before and after the method execution. The advice argument is the pointcut and it says to apply when the @LogElapsedTime annotation is used.

The goal is to inject extra code to log how much time some methods take to finish. As you can see it’s very flexible and to include any method in this flow just needs an annotation.

@Aspect
@Component
@Slf4j
public class ExampleAspect {

    @Around("@annotation(com.sample.aop.LogElapsedTime)")
    public Object logElapsedTime(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object proceed = joinPoint.proceed();
        log.info(String.format("%s took %d ms", joinPoint.getSignature(), System.currentTimeMillis() - startTime));
        return proceed;
    }

}

Testing

The happy part, to test it and see how it works!

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class LogElapsedTimeTest {

    @Autowired
    private ExampleService service;

    @Test
    public void validateLogElapsedTimeAnnotation() throws InterruptedException {
        service.simulateSlowMethod();
    }

}

The complete code is available in my Github repository.

I hope it helps to understand better.

References:

[1] https://docs.spring.io/spring-framework/docs/2.5.x/reference/aop.html

[2] https://mkyong.com/spring/spring-aop-examples-advice/

[3] https://www.baeldung.com/spring-aop-annotation

Leave a comment