What does Spring's @AfterReturning advice do, and when does it run?
answer
- Runs only on normal return
- Skipped on exception (that's @AfterThrowing)
- Observer only — can't replace return value
- returning= binds the result
- @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@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
Must know it runs only on success and cannot change the result.
Should contrast with @After/@AfterThrowing and know the returning binding.
Explains execution ordering and mutation-vs-replacement nuance.
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)