Master Spring AOP: Essential Annotations, Execution Order, and Common Pitfalls

This article revisits the fundamentals of Spring AOP, detailing its core annotations such as @Before, @After, @Around, and their execution sequence, while providing a complete demo project, code examples, and insights into common pitfalls like proxy failures and multi‑aspect ordering.

Programmer DD
Programmer DD
Programmer DD
Master Spring AOP: Essential Annotations, Execution Order, and Common Pitfalls

Hello, I'm DD. I emphasize the importance of fundamentals; many jump straight to Spring Boot/Cloud without solid Spring AOP knowledge, so here's a concise guide.

Common Spring AOP Annotations

Review of frequently used annotations:

@Before – executes before the target method.

@After – executes after the target method (always).

@AfterReturning – runs after successful return (no exception).

@AfterThrowing – runs when an exception is thrown.

@Around – surrounds the target method execution.

Common Questions

1. What is the full execution order of Spring AOP notifications, and does Spring Boot 2 affect it?

2. What common pitfalls have you encountered with AOP?

Example Code

We build a simple Spring AOP demo using Spring Boot.

Configuration

Use start.spring.io or IDE to generate a Spring Boot project with the following Gradle build script:

plugins {
    id 'org.springframework.boot' version '2.6.3'
    id 'io.spring.dependency-management' version '1.0.11.RELEASE'
    id 'java'
}

group 'io.zhengsh'
version '1.0-SNAPSHOT'

repositories {
    mavenCentral()
    maven { url 'https://repo.spring.io/milestone' }
    maven { url 'https://repo.spring.io/snapshot' }
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-actuator'
    implementation 'org.springframework.boot:spring-boot-starter-aop'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

tasks.named('test') {
    useJUnitPlatform()
}

Interface

Define a service interface to illustrate JDK dynamic proxy vs. CGLIB:

public interface CalcService {
    public int div(int x, int y);
}

Implementation

@Service
public class CalcServiceImpl implements CalcService {
    @Override
    public int div(int x, int y) {
        int result = x / y;
        System.out.println("====> CalcServiceImpl called, result: " + result);
        return result;
    }
}

AOP Aspect

Declare an aspect with @Aspect and @Component, and enable proxy support with @EnableAspectJAutoProxy if needed.

@Aspect
@Component
public class MyAspect {

    @Pointcut("execution(* io.zhengsh.spring.service.impl..*.*(..))")
    public void divPointCut() {}

    @Before("divPointCut()")
    public void beforeNotify() {
        System.out.println("----===>> @Before I am before advice");
    }

    @After("divPointCut")
    public void afterNotify() {
        System.out.println("----===>> @After I am after advice");
    }

    @AfterReturning("divPointCut")
    public void afterReturningNotify() {
        System.out.println("----===>> @AfterReturning I am after returning advice");
    }

    @AfterThrowing("divPointCut")
    public void afterThrowingNotify() {
        System.out.println("----===>> @AfterThrowing I am exception advice");
    }

    @Around("divPointCut")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        Object retVal;
        System.out.println("----===>> @Around before AAA");
        retVal = proceedingJoinPoint.proceed();
        System.out.println("----===>> @Around after BBB");
        return retVal;
    }
}

Test Class

A simple test that acts like a main method to invoke the service.

Execution Results

With Spring 4.x and Spring Boot 1.5.9, the around advice executes innermost.

With Spring 5.3.15 and Spring Boot 2.6.3, the behavior remains consistent.

Multiple Aspects

When several aspects are present, use @Order to define precedence; lower numbers have higher priority.

Proxy Failure Scenario

Self‑invocation within the same bean bypasses the proxy, causing advice on the called method to be ignored.

@Service
public class AService {
    public void a() {
        System.out.println("...... a");
        b();
    }
    public void b() {
        System.out.println("...... b");
    }
}
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaProxyBackend Developmentannotationsspring-aopaspectj
Programmer DD
Written by

Programmer DD

A tinkering programmer and author of "Spring Cloud Microservices in Action"

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.