Skip to main navigation Skip to main content Skip to page footer

Spring Core - How to implement and deploy Advices using Spring AOP

| Java Spring Boot

AOP solves critical issues related to cross-cutting concerns by modularizing them into reusable and maintainable aspects. It simplifies code, reduces duplication, and enhances the separation of concerns, making it a powerful tool in modern application development.

Add Spring AOP Dependency

Add the necessary Spring AOP dependency to your pom.xml, if you're using Maven, or build.gradle in case of Gradle:

// MAven
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>5.3.26</version> <!-- Use the latest compatible version -->
</dependency>

// Gradle 
implementation 'org.springframework:spring-aspects:5.3.26'

Enable AOP in Your Spring Application

Enable AspectJ Auto Proxying in your Spring configuration by adding the @EnableAspectJAutoProxy annotation.

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@EnableAspectJAutoProxy
public class AppConfig {
    // Other bean definitions
}

Define the Target Service

Create a service class that will have methods where you want to apply the advice.

package com.example.service;

import org.springframework.stereotype.Service;

@Service
public class OrderService {

    public void placeOrder() {
        System.out.println("Order placed successfully!");
    }

    public void cancelOrder() {
        System.out.println("Order canceled.");
    }
}

Create the Aspect

Define an aspect class to implement the advice. An aspect contains:

  • Pointcuts: Specify where the advice should be applied.
  • Advices: Define the behavior to apply.
package com.example.aspect;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect {

    // Pointcut: Matches all methods in the service package
    @Before("execution(* com.example.service.*.*(..))")
    public void logBefore() {
        System.out.println("Logging BEFORE method execution.");
    }

    @AfterReturning(pointcut = "execution(* com.example.service.*.*(..))", returning = "result")
    public void logAfterReturning(Object result) {
        System.out.println("Logging AFTER method returned successfully.");
    }

    @AfterThrowing(pointcut = "execution(* com.example.service.*.*(..))", throwing = "exception")
    public void logAfterThrowing(Exception exception) {
        System.out.println("Logging AFTER method threw an exception: " + exception.getMessage());
    }

    @Around("execution(* com.example.service.*.*(..))")
    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("Logging AROUND method execution: BEFORE");
        Object result;
        try {
            result = joinPoint.proceed(); // Proceed with the target method
        } catch (Throwable ex) {
            System.out.println("Logging AROUND method execution: EXCEPTION");
            throw ex;
        }
        System.out.println("Logging AROUND method execution: AFTER");
        return result;
    }
}

Run the Application

Create a main method or use a Spring Boot application class to run the application.

package com.example;

import com.example.service.OrderService;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;

@SpringBootApplication
public class AopDemoApplication {

    public static void main(String[] args) {
        ApplicationContext context = SpringApplication.run(AopDemoApplication.class, args);

        // Get the OrderService bean and call its methods
        OrderService orderService = context.getBean(OrderService.class);
        orderService.placeOrder();
        orderService.cancelOrder();
    }
}

Output Example

When the application runs, the following output will appear in the console:

Logging BEFORE method execution.
Order placed successfully!
Logging AFTER method returned successfully.
Logging AROUND method execution: BEFORE
Order canceled.
Logging AROUND method execution: AFTER

If an exception occurs in the placeOrder or cancelOrder method, the @AfterThrowing advice will log it.

Back