How to implement Aspect Oriented Programming in Spring Boot?

In your web app ,

Often you need to implement certain logic which is common across different parts of your application.

Like purely technical aspects like logging , security etc.

You don’t want to repeat this logic in each part of the code.

And you also don’t want to clutter your code by including logic for these aspects.

Wouldn’t be nice if you separate this aspects which are common across different parts of your application ?

That is what exactly is done by Aspect Oriented Programming.

You can implement these “cross cutting” aspects separately.

Let’s see how to implement this in Spring Boot.

Let’s take one of the cross cutting concerns:

Finding Execution Time of a method.

And you want to find this only for public methods.

Let’s implement this , below are the steps:

STEP 1: Include AOP dependency

You will need to add the spring-aspects dependency to your project’s classpath.

This can be done by adding the following to your project’s pom.xml file (if you are using Maven) or build.gradle file (if you are using Gradle):

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
</dependency>

STEP 2: Create an Aspect class:

This is a regular Java class that contains the cross-cutting logic that you want to apply.

The aspect class should be annotated with @Aspect.

@Aspect
@Component
public class ExecutionTimeAspect {

 
}

STEP 3: Define PointCuts:

These are expressions that define where the aspect should be applied.

Pointcuts are defined using the @Pointcut annotation.

For our example, we need to define a pointcut that applies to all public methods in a particular package

@Aspect
@Component
public class ExecutionTimeAspect {



    @Pointcut("execution(public * com.example.demo.*.*(..))")
    public void publicMethod() {}


}

In the above example we are applying aspect to all public methods which return any data type ( denoted by wildcard *) and for all classes in the package com.example.demo.

STEP 4: Define Advice:

This is the logic that you want to execute when a pointcut is matched.

Advice is defined using the @Before, @After, @Around, @AfterReturning, @AfterThrowing annotations.

@Before means the aspect will be applied before the method execution starts

@After means the aspect will be applied after the method finishes execution whether successful or with exception

@AfterReturning means the aspect will be applied after the method finishes execution sucessfully

@AfterThrowing means the aspect will be applied when an exception is thrown.

@Around means the aspect will be applied around the method (will consider starting and ending of the method)

For our example , we want to know the execution time of the method.

So we will use @Around:

@Aspect
@Component
public class ExecutionTimeAspect {

    private static final Logger LOGGER = LoggerFactory.getLogger(ExecutionTimeAspect.class);

    @Pointcut("execution(public * com.example.demo.*.*(..))")
    public void publicMethod() {}

    @Around("publicMethod()")
    public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        Object proceed = joinPoint.proceed();
        long executionTime = System.currentTimeMillis() - start;
        LOGGER.info(joinPoint.getSignature() + " executed in " + executionTime + "ms");
        return proceed;
    }
}

STEP 5: Enable AOP in your Spring Configuration:

This can be done by adding the annotation @EnableAspectAutoProxy in your main class:

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@SpringBootApplication
@EnableAspectJAutoProxy
public class Aopdemo1Application {

	public static void main(String[] args) {
		SpringApplication.run(Aopdemo1Application.class, args);
	}

}

STEP 6: Test

Let’s create a public method and test this out.

I have created a REST API (added spring boot starter web dependency in pom.xml) :

package com.example.demo;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {

	
	
	@GetMapping("/test")
	public String test() {
		
		
		try {
			Thread.sleep(5000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return "Hello World!";
	}
}

I have added the code to sleep for 5 seconds .

Now run the application.

You can see the below output in the logs:

The return type is String

The method is test()

And the time is approximately 5 seconds.

All these are printed in the console.

That’s it!


Posted

in

by

Comments

Leave a Reply

Discover more from The Full Stack Developer

Subscribe now to keep reading and get access to the full archive.

Continue reading