Advice Types
Advice Types
In Spring AOP, an advice is the action your aspect takes at a particular join point. Spring gives you five distinct advice annotations, each with a different relationship to the target method's execution. Picking the right one is not a matter of style — each type has specific guarantees, specific capabilities, and specific trade-offs that affect correctness, performance, and maintainability.
All five are in the package org.aspectj.lang.annotation and work with Spring 6 / Spring Boot 3 on the jakarta.* namespace.
@Before — Run Before the Method
@Before advice executes before the target method is called. It cannot stop execution (unless it throws an exception) and it cannot see the method's return value because the method has not run yet.
Typical uses: access-control checks, input validation, pre-condition assertions, logging that a call is about to happen.
@Before always runs before the method body. If it throws, the target method is never invoked and Spring propagates the exception to the caller. This makes it the right hook for gate-keeping logic.
@After — Run After the Method (Finally)
@After advice runs after the method completes — whether it returned normally or threw an exception. Think of it as the aspect equivalent of a finally block. It cannot access the return value and it cannot suppress or replace the exception.
Typical uses: releasing resources, clearing thread-local state, audit trail "end of call" records.
@AfterReturning and @AfterThrowing instead — they give you that discrimination.
@AfterReturning — Run After a Normal Return
@AfterReturning fires only when the target method completes without throwing. Its key superpower: you can bind the actual return value and inspect (or log) it. You cannot replace the return value from this advice type.
You can narrow the type of the bound parameter. If you write Object savedUser, it matches any return type. If you write User savedUser, Spring only applies the advice when the return value is assignment-compatible with User.
@AfterReturning is the cleanest place to populate a cache after a successful database read. The method ran, it succeeded, and you now have the result — no try/catch boilerplate in your service layer.
@AfterThrowing — Run When an Exception Escapes
@AfterThrowing fires only when the target method throws an exception that propagates past it. You can bind the exception, log it, alert monitoring systems, or enrich it — but the exception still propagates unless you throw a different one.
As with @AfterReturning, you can constrain the exception type. Declaring RuntimeException ex means checked exceptions pass through without triggering this advice. Declaring Throwable ex catches everything.
@Around — Full Control Over Execution
@Around is the most powerful advice type. It wraps the entire method call: you decide if and when to invoke the target method, you can modify arguments before calling it, and you can modify or replace the return value after it returns. This power comes with responsibility — if you forget to call proceed(), the target method never executes.
pjp.proceed(). The method's return type might be void (in which case the value is null and discarding it is fine), but for all other types the caller is waiting for that value. Forgetting the return statement compiles fine but produces silent null bugs at runtime.
Execution Order When Multiple Advices Apply
When several advice methods match the same join point, Spring invokes them in a defined order around the call stack:
@Around(beforeproceed())@Before- Target method executes
@AfterReturningor@AfterThrowing(whichever applies)@After@Around(afterproceed()returns)
When two advices of the same type in different aspects apply to the same join point, you control their relative order with @Order(n) on the aspect class — lower number runs outermost (first before, last after).
Choosing the Right Advice Type
- Need to gate or validate before execution? Use
@Before. - Need guaranteed cleanup regardless of outcome? Use
@After. - Need the return value to log, cache, or react on success? Use
@AfterReturning. - Need to detect, log, or enrich a specific exception? Use
@AfterThrowing. - Need to modify arguments, suppress exceptions, or replace the return value? Use
@Around.
Prefer the least-powerful type that satisfies your requirement. @Around is capable of everything, but using it for simple logging obscures intent and introduces the risk of accidentally swallowing exceptions or return values. Reserve it for cross-cutting concerns that genuinely need full control: caching, retries, transactions, circuit breakers.
Summary
Spring AOP's five advice types form a spectrum from minimal responsibility (@Before, @After) to complete control (@Around). Each type has a clear contract: what it sees, when it runs, and what it can change. Matching the right type to your requirement keeps aspect code readable, prevents subtle bugs, and signals intent to the next developer. In the following lessons you will put this into practice with @Around and the ProceedingJoinPoint API, then build real-world logging and security aspects.