What is org.aopalliance.intercept.MethodInterceptor in Spring AOP, and how does its invoke() method work?
answer
- AOP Alliance around advice
- invoke(MethodInvocation) -> proceed()
- no proceed() = target skipped
- can replace return value
- singleton, keep stateless
basics
~10 sMethodInterceptor is Spring's low-level 'around' advice. Its invoke(MethodInvocation) method runs your code, then calls invocation.proceed() to invoke the real target method, and can run more code after — like a wrapper around each call.
solid answer
~40 sMethodInterceptor comes from the AOP Alliance package (org.aopalliance.intercept) and is the most general advice type in Spring AOP — an 'around' advice. It has one method: Object invoke(MethodInvocation invocation) throws Throwable. Inside, you can run logic before the target call, then call invocation.proceed() to advance to the next interceptor in the chain (and ultimately the target method), then run logic after, inspect or replace the return value, and catch/translate exceptions. If you never call proceed(), the target method never runs — useful for caching or short-circuiting. Multiple interceptors form a chain, each holding the MethodInvocation and calling proceed() to pass control down. It is the low-level equivalent of @AspectJ's @Around; the simpler advice types (before/after-returning/throws) are adapted into interceptors internally.
code
java · 16 linesimport org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class TimingInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
long start = System.nanoTime();
try {
Object result = invocation.proceed(); // call next interceptor / target
return result; // could return a different object to replace it
} finally {
long micros = (System.nanoTime() - start) / 1000;
System.out.println(invocation.getMethod().getName() + " took " + micros + "us");
}
}
}go deeper
Know it's an 'around' wrapper and that proceed() calls the real method.
Explain the chain, replacing return values, and short-circuiting by skipping proceed().
Relate it to @Around, describe MethodInvocation internals and self-invocation limits.
Discuss adapter conversion of simpler advice into interceptors and thread-safety of shared interceptor instances.
### What it is `org.aopalliance.intercept.MethodInterceptor` is an interface from the **AOP Alliance** project (a vendor-neutral AOP interface set that Spring adopts, package `org.aopalliance.*`). It is the **most powerful and general advice type** in Spring's classic AOP API — an **around advice**. All the simpler advice types (`MethodBeforeAdvice`, `AfterReturningAdvice`, `ThrowsAdvice`) are internally converted into `MethodInterceptor`s by adapter classes before Spring builds the proxy's interceptor chain. ### The single method ```java Object invoke(MethodInvocation invocation) throws Throwable; ``` `MethodInvocation` (also AOP Alliance, extends `Joinpoint`) gives you: - `proceed()` — advance to the **next interceptor in the chain**, or, if this is the last one, invoke the **actual target method**. Returns the target's result. - `getArguments()` — the call arguments (you may mutate the array to change what the target sees). - `getMethod()` — the reflective `java.lang.reflect.Method`. - `getThis()` — the target object being proxied. ### Mechanics of the chain A Spring AOP proxy holds an ordered list of interceptors (the advice chain) plus the target. When a proxied method is called, Spring builds a `ReflectiveMethodInvocation` and calls the first interceptor's `invoke`. Each interceptor decides whether/when to call `proceed()`. Calling `proceed()` drives the invocation one step further; the chain is essentially a recursive descent. The **last** `proceed()` reflectively invokes the target method. ### What you can do inside invoke() - **Before**: log, validate, start a timer, open a transaction/lock. - **Skip the target**: return a cached value without calling `proceed()` (short-circuit). - **After (normal)**: inspect the returned `Object`, and — unlike `AfterReturningAdvice` — you may **replace** it by returning a different object. - **After (exception)**: wrap `proceed()` in try/catch to translate or suppress exceptions. - **Finally**: stop a timer, release a lock (put it in a `finally` block). ### Gotchas - **You must call `proceed()`** (usually exactly once) unless you deliberately short-circuit — forgetting it silently skips the real method. - `invoke` declares `throws Throwable`; don't swallow exceptions unintentionally. - Self-invocation still applies: a proxy only intercepts calls that go **through the proxy**, so a target method calling `this.other()` bypasses the interceptor. - An interceptor is a **singleton shared across all invocations** — keep it stateless or thread-safe; per-call state lives on the `MethodInvocation`. ### When to use Use a raw `MethodInterceptor` when you need full around control (caching, retry, timing, transaction-like semantics) in the low-level API, or when integrating an existing AOP-Alliance interceptor. For most application code, `@Around` in `@AspectJ` style is the modern, more readable equivalent — the classic API is mostly seen in framework/library internals and legacy XML configs.
- What happens if invoke() never calls invocation.proceed()?The target method (and any later interceptors in the chain) never runs. invoke() must return something for the caller. This is intentional for short-circuiting patterns like caching or access denial.
- How is MethodInterceptor related to @Around in @AspectJ?They are conceptually the same 'around' advice. @Around with ProceedingJoinPoint.proceed() is the annotation-style equivalent; under the hood @AspectJ around advice is also driven through a MethodInterceptor in the chain.
saying these in an interview costs you the question
- Thinking invoke() runs only before or only after the method (it wraps around it)
- Believing proceed() is optional decoration rather than the call that actually invokes the target
- Assuming a new interceptor instance is created per call (it's a shared singleton)
- Confusing MethodInterceptor (org.aopalliance) with a Servlet/HTTP interceptor