Describe Spring's classic advice interfaces MethodBeforeAdvice, AfterReturningAdvice, and ThrowsAdvice — their method signatures and semantics.
answer
- before(Method,args,target) — throw to veto
- afterReturning is void — can't replace result
- ThrowsAdvice = marker, afterThrowing by reflection
- last param must be Throwable subtype (1 or 4 args)
- all adapted into MethodInterceptors
basics
~10 sThey are Spring's simpler advice types. MethodBeforeAdvice runs before a method, AfterReturningAdvice runs after it returns successfully, and ThrowsAdvice runs when it throws. They observe the call but can't change the return value.
solid answer
~40 sBeyond the general MethodInterceptor, Spring's classic API offers focused advice interfaces. MethodBeforeAdvice has before(Method, Object[] args, Object target) — runs before the target; throwing from it aborts the call. AfterReturningAdvice has afterReturning(Object returnValue, Method, Object[] args, Object target) — runs only on normal return; it can see the return value but, being void, cannot replace it (though it may throw to turn success into failure). ThrowsAdvice is a marker interface with no methods; you add one or more afterThrowing methods whose last parameter is a Throwable subtype (optionally preceded by Method, Object[], Object), and Spring reflectively picks the most specific match when an exception propagates. All three are internally wrapped into MethodInterceptors via adapters (MethodBeforeAdviceAdapter, etc.) before the proxy chain is built. They are more constrained but more declarative than a raw interceptor.
code
java · 25 linesimport java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.ThrowsAdvice;
class AuditBefore implements MethodBeforeAdvice {
public void before(Method m, Object[] args, Object target) {
System.out.println("about to call " + m.getName());
}
}
class LogResult implements AfterReturningAdvice {
public void afterReturning(Object ret, Method m, Object[] args, Object target) {
System.out.println(m.getName() + " returned " + ret); // cannot replace ret
}
}
class TranslateErrors implements ThrowsAdvice { // marker: methods found reflectively
public void afterThrowing(IllegalArgumentException ex) {
System.out.println("bad argument: " + ex.getMessage());
}
public void afterThrowing(Method m, Object[] args, Object target, RuntimeException ex) {
System.out.println(m.getName() + " failed: " + ex);
}
}go deeper
Name the three and when each fires (before / on success / on exception).
Give exact signatures and the void-return limitation of afterReturning; know ThrowsAdvice is a marker.
Explain reflective method resolution for ThrowsAdvice and adapter conversion into interceptors.
Contrast with @AspectJ @Before/@AfterReturning/@AfterThrowing and discuss the DefaultAdvisorAdapterRegistry extension point.
### Big picture Spring's classic (pre-@AspectJ) AOP defines several **advice** types, all sub-types of the AOP Alliance marker `org.aopalliance.aop.Advice`. `MethodInterceptor` is the fully general 'around' one; the three below are **narrower, single-purpose** advices that are easier to write when you don't need full around control. Internally Spring converts each into a `MethodInterceptor` using an **advisor adapter** (`MethodBeforeAdviceAdapter`, `AfterReturningAdviceAdapter`, `ThrowsAdviceAdapter`) registered in the `DefaultAdvisorAdapterRegistry`, so the proxy always ultimately runs a chain of interceptors. ### 1. MethodBeforeAdvice (`org.springframework.aop.MethodBeforeAdvice`) ```java void before(Method method, Object[] args, Object target) throws Throwable; ``` - Runs **before** the target method executes. - Can inspect (and mutate) the `args` array. - Cannot prevent execution by returning, but **throwing** an exception aborts the call and propagates to the caller (the target never runs). - Cannot see or alter the return value. ### 2. AfterReturningAdvice (`org.springframework.aop.AfterReturningAdvice`) ```java void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable; ``` - Runs **only after the target returns normally** (not on exception). - Receives the `returnValue` and can read it, but the method is **void** — it **cannot replace** the return value. (To modify the result you need a `MethodInterceptor`.) - May **throw** to convert a successful call into a failure. ### 3. ThrowsAdvice (`org.springframework.aop.ThrowsAdvice`) - A **marker interface with no methods**. You add one or more methods that Spring discovers **reflectively** by convention. Valid signatures: ```java void afterThrowing(SomeException ex); // or the 4-arg form: void afterThrowing(Method method, Object[] args, Object target, SomeException ex); ``` - The **last parameter must be a `Throwable` subclass**; only the 1-arg and 4-arg forms are allowed (no 2- or 3-arg forms). - Runs when the target throws a matching exception. Spring picks the **most specific** matching `afterThrowing` method (by the throwable's runtime type). - After the advice runs, the **original exception still propagates** unless the advice itself throws a different exception. ### Common gotchas - **AfterReturningAdvice cannot change the return value** — a frequent misconception; you must switch to `MethodInterceptor` for that. - **ThrowsAdvice methods are found by reflection**, not by an interface contract — a typo in the method name means it silently never fires. - The `afterReturning`/`before` methods run only on their respective outcome; if you need guaranteed cleanup on both success and failure, use an interceptor with try/finally (there is no separate 'after (finally)' classic interface — that's `@After` in @AspectJ). - Throwing from `before` is the classic way to veto a call (used e.g. by security advice). - All advices are **singletons** shared across invocations — keep them stateless. ### When to use which - **before**: validation, security checks, argument logging, veto-by-throw. - **afterReturning**: audit/log successful results, post-conditions, cache population (read-only on the value). - **throws**: exception translation/logging without altering business flow. - **around (MethodInterceptor)**: anything needing timing, retry, result substitution, or short-circuiting.
- Can AfterReturningAdvice modify the value returned to the caller?No. Its afterReturning method is void, so it can only observe the return value (or throw to fail the call). To transform the result you must use a MethodInterceptor and return a different object from invoke().
- Why does ThrowsAdvice have no methods, and how does Spring know which to call?It is a marker interface; Spring introspects the implementation for methods named afterThrowing whose last parameter is a Throwable subtype (1-arg or 4-arg forms). At runtime it invokes the most specific match for the thrown exception's type.
saying these in an interview costs you the question
- Claiming AfterReturningAdvice can change/replace the return value
- Thinking ThrowsAdvice has an interface method you override
- Saying afterReturning also runs when the method throws
- Believing before() can skip the method by returning (only throwing vetoes it)
- Expecting a 2- or 3-argument afterThrowing signature to work