skip to content

@AfterReturning Advice

@AfterReturning runs only on a successful return and binds the returned value, but it cannot replace it. The contrast with @Around is the whole point of the question.

part ofSpring Frameworkoverview, primer and where to startread it →
on this pageshow

questions

5

What does Spring's @AfterReturning advice do, and when does it run?

level: juniorimportance: must knowfreq 60%

answer

  1. Runs only on normal return
  2. Skipped on exception (that's @AfterThrowing)
  3. Observer only — can't replace return value
  4. returning= binds the result
  5. @After = finally; @AfterReturning = success-only

basics

~10 s

@AfterReturning is AOP advice that runs after an advised method finishes successfully (returns normally). It does NOT run if the method throws an exception. It can read the returned value but cannot replace it.

solid answer

~40 s

@AfterReturning is one of Spring AOP's advice types (annotation on a method inside an @Aspect class). It executes after a matched method — the join point — completes by returning normally. Crucially, it only fires on a successful return; if the method throws, the advice is skipped and @AfterThrowing runs instead. You typically use it to observe or log a successful outcome, and you can bind the actual return value via the returning attribute, e.g. @AfterReturning(pointcut="...", returning="result"). Unlike @Around, @AfterReturning is a pure observer: it cannot substitute a different return value and cannot stop the return. Contrast it with @After (finally-style, runs on both success and exception) and @Before (runs before the call).

code

java · 15 lines
java
@Aspect
@Component
public class AuditAspect {

    private static final Logger log = LoggerFactory.getLogger(AuditAspect.class);

    @AfterReturning(
        pointcut = "execution(* com.app.OrderService.placeOrder(..))",
        returning = "order")
    public void afterPlaceOrder(JoinPoint jp, Order order) {
        // Runs ONLY if placeOrder returned normally.
        log.info("Order {} placed for {}", order.getId(), jp.getArgs()[0]);
        // Cannot replace 'order' here; only @Around could do that.
    }
}

go deeper

for a junior

Must know it runs only on success and cannot change the result.

for a middle

Should contrast with @After/@AfterThrowing and know the returning binding.

for a senior

Explains execution ordering and mutation-vs-replacement nuance.

for a principal

Frames it as observer-only design and notes proxy/self-invocation limits.

## What it is `@AfterReturning` is one of the five advice annotations in Spring AOP: `@Before`, `@After`, `@AfterReturning`, `@AfterThrowing`, and `@Around`. **Advice** is code that runs at a chosen point in your program; a **join point** in Spring AOP is always a method execution on a Spring-managed bean; a **pointcut** is the predicate that selects which join points get advised. `@AfterReturning` is declared as a method inside a class annotated with `@Aspect` (and registered as a Spring bean, e.g. via `@Component`). ## When it runs It runs **after** the advised method finishes, but **only on a normal (successful) return**. If the method throws any exception, `@AfterReturning` is skipped — that path is handled by `@AfterThrowing`. This is the key difference from `@After`, which behaves like a `finally` block and runs on **both** success and exception. Execution order around a method: `@Around` (before proceed) → `@Before` → method body → `@AfterReturning` (or `@AfterThrowing`) → `@After` → `@Around` (after proceed). ## Binding the return value With the `returning` attribute you name a parameter that receives the method's return value: ```java @AfterReturning(pointcut = "execution(* com.app.OrderService.*(..))", returning = "result") public void log(JoinPoint jp, Object result) { ... } ``` The string `"result"` must match the advice-method parameter name, not the return value expression. ## What it CANNOT do - It **cannot change the value returned to the caller**. It receives the value but has no mechanism to replace it — only `@Around` can substitute a return value (by returning something other than `proceed()`'s result). - It **cannot suppress or convert an exception** — it simply doesn't run when one is thrown. ## Nuance: mutation vs replacement While you can't *replace* the returned reference, if the returned object is **mutable** you can mutate its state (e.g. call setters on a returned entity), and the caller sees those mutations because it holds the same reference. That is a side effect, not a return-value substitution, and is generally discouraged. ## When to use Logging/auditing successful operations, publishing 'success' metrics or events, cache population based on a returned value, or triggering follow-up work only on success. For anything that must alter the result or handle failures, use `@Around` or `@AfterThrowing`. ## Proxy caveat Like all Spring AOP, advice only applies when the call goes through the proxy — self-invocation (a method calling another method on `this`) bypasses the proxy and the advice does not fire.

  • What runs instead of @AfterReturning if the method throws?
    @AfterThrowing (if present) runs, and @After runs in both cases. @AfterReturning is simply skipped on any thrown exception.
  • How is @AfterReturning different from @After?
    @After is a finally-style advice that runs whether the method returns or throws. @AfterReturning runs only on successful (normal) return and can bind the returned value.

saying these in an interview costs you the question

  • Saying @AfterReturning runs even when the method throws
  • Claiming you can change/replace the return value from @AfterReturning
  • Confusing it with @After (finally semantics)

context

open as a page

How do you bind and use a method's return value inside @AfterReturning, and what are the naming rules?

level: middleimportance: must knowfreq 55%

basics

~10 s

Add returning="paramName" to @AfterReturning and declare a matching parameter of that name in the advice method. The parameter receives the returned value. The name must match the parameter, not the pointcut expression.

open as a page

Why can't @AfterReturning modify the value returned to the caller, and when should you reach for @Around instead?

level: seniorimportance: should knowfreq 45%

basics

~20 s

@AfterReturning is an observer: Spring gives it the return value but provides no way to substitute a different one — its own return type is ignored by the framework. To transform or replace the result you need @Around, which controls what proceed() returns.

open as a page

In what order do @Before, @After, @AfterReturning, @AfterThrowing, and @Around fire around a single method, and how does @AfterReturning fit on the success vs failure paths?

level: seniorimportance: should knowfreq 40%

basics

~10 s

Around-before → Before → method → (on success) AfterReturning, (on failure) AfterThrowing → After (always) → Around-after. @AfterReturning fires only on the success path, before @After, and never on the exception path.

open as a page

As a principal engineer, how would you decide between @AfterReturning and @Around for a cross-cutting concern like response auditing or metrics, and what pitfalls would you guard against?

level: principalimportance: nice to knowfreq 25%

basics

~20 s

Prefer the least-powerful advice that expresses intent: @AfterReturning for read-only success reactions (audit, metrics, cache-put). Use @Around only when you must transform the result, time the whole call, short-circuit, or handle exceptions. Guard against proxy self-invocation and non-deterministic aspect ordering.

open as a page