What is the Advised interface and what can you do by casting a live Spring AOP proxy to it?
answer
- every Spring proxy castable to Advised
- getAdvisors() = Advisor[] = pointcut + advice
- add/remove advisor at runtime, chain cache invalidated
- frozen -> AopConfigException on mutation
- getTargetSource / setTargetSource
basics
~20 sAdvised is the interface every Spring AOP proxy implements. Cast a proxy to Advised to inspect or change it at runtime: read the list of advisors, add or remove advice, and see the target and proxy settings.
solid answer
~40 s`Advised` is the configuration view of a Spring AOP proxy: `ProxyFactory` implements it, and every proxy Spring creates can be cast to it. Through it you reach the *advisor chain* via `getAdvisors()` (each `Advisor` = a `Pointcut` plus an `Advice`), mutate it with `addAdvice`, `addAdvisor`, `removeAdvisor`, `removeAdvice`, and inspect/replace the `TargetSource` with `getTargetSource`/`setTargetSource`. It also exposes config flags: `isProxyTargetClass()`, `isExposeProxy()`, `isFrozen()`, `getTargetClass()`, `getProxiedInterfaces()`. Changes take effect on the next invocation because the interceptor chain is rebuilt/cached from the advisors. If the proxy config was created with `frozen=true`, mutation methods throw `AopConfigException`. This is the mechanism that lets tools and frameworks reconfigure a live proxy without rebuilding it.
code
java · 20 lines// proxy came from the container or a ProxyFactory
if (AopUtils.isAopProxy(bean)) {
Advised advised = (Advised) bean;
// Inspect the advisor chain
for (Advisor a : advised.getAdvisors()) {
System.out.println(a.getAdvice().getClass().getSimpleName());
}
// Add behavior to the LIVE proxy (next call reflects it)
advised.addAdvice((MethodInterceptor) inv -> {
long t = System.nanoTime();
try { return inv.proceed(); }
finally { System.out.println(inv.getMethod().getName()
+ " took " + (System.nanoTime() - t) + "ns"); }
});
// Swap the underlying target without rebuilding references
// advised.setTargetSource(new SingletonTargetSource(newTarget));
}go deeper
Know Advised lets you read getAdvisors() off a proxy.
Explain runtime add/remove of advisors and the frozen restriction.
Discuss chain caching/invalidation, thread-safety of live reconfiguration, and AopProxyUtils.ultimateTargetClass.
Weigh runtime proxy mutation vs. immutable configuration for maintainability and observability in a large codebase.
## Definition `org.springframework.aop.framework.Advised` is the interface that represents the *configuration* behind an AOP proxy — the target, the interfaces, and the ordered chain of `Advisor`s. `AdvisedSupport` (the base of `ProxyFactory`) implements it, and crucially **every proxy Spring generates also implements `Advised`**, so you can downcast any Spring AOP proxy: `Advised advised = (Advised) proxy;`. ## Advisor chain `getAdvisors()` returns `Advisor[]`. An `Advisor` bundles two things: - a `Pointcut` (which classes/methods to match), and - an `Advice` (the behavior). When you call `addAdvice(someInterceptor)`, Spring wraps it in a `DefaultPointcutAdvisor` whose pointcut is `Pointcut.TRUE` (matches everything). `addAdvisor(pos, advisor)` lets you insert at a specific index, controlling execution order — advisors run in list order, outermost first. ## Mutating a live proxy Because the proxy delegates to its `AdvisedSupport`, you can, at runtime: - `advised.addAdvice(newInterceptor)`, - `advised.addAdvisor(advisor)`, - `advised.removeAdvisor(index)` / `removeAdvisor(advisor)`, - `advised.removeAdvice(advice)`, - and swap the target via `advised.setTargetSource(newTargetSource)`. The interceptor chain for each method is cached in `AdvisedSupport.methodCache`; mutating the advisors invalidates that cache so the next call recomputes and reflects the change. There is no need to rebuild the proxy. ## Inspection, freezing and helpers **Inspection methods.** `getTargetClass()`, `getProxiedInterfaces()`, `isInterfaceProxied(Class)`, `getTargetSource()`, `isProxyTargetClass()`, `isExposeProxy()`, `isPreFiltered()`, and (from `ProxyConfig`) `isFrozen()`, `isOptimize()`. **Frozen config.** `ProxyConfig.setFrozen(true)` marks the configuration immutable. After freezing, any `addAdvisor`/`removeAdvisor`/`setTargetSource` throws `AopConfigException("Cannot advise... frozen")`. Spring sets `frozen=true` when `<aop:config>`/optimizations allow it, enabling a faster fixed chain. So code that tries to reconfigure a frozen proxy fails at runtime. **AopUtils / AopProxyUtils helpers.** In practice you often combine `Advised` with helpers: - `AopUtils.isAopProxy(obj)`, `isJdkDynamicProxy`, `isCglibProxy`; - and `AopProxyUtils.ultimateTargetClass(obj)` to get the real class behind (possibly nested) proxies. `Advised.getTargetSource().getTarget()` retrieves the underlying object. ## Gotchas - (1) Not all proxies are Spring AOP proxies — a JDK proxy created by other code isn't `Advised`; guard with `AopUtils.isAopProxy`. - (2) Mutating advisors on a proxy shared by many threads is not automatically synchronized for readers mid-call — treat runtime reconfiguration as a rare, coordinated operation. - (3) Removing the last advice does not un-proxy the object; you still go through the (now pass-through) chain. - (4) `frozen` proxies silently forbid changes — check `isFrozen()` first. ## When to use - Introspection in tests/diagnostics ('what advisors are on this bean?'), - frameworks that dynamically add/remove cross-cutting behavior, - or migrating a target behind a proxy (via `setTargetSource`) without recreating references. In normal app code you rarely touch `Advised` directly.
- If you addAdvice() to a proxy that a request thread is currently executing, does that in-flight call pick up the new advice?No. The interceptor chain for the currently-executing invocation was already resolved; the new advice is picked up on the next invocation after the advisor list mutation invalidates the method chain cache.
saying these in an interview costs you the question
- Claiming you must rebuild the proxy to change its advice
- Assuming any Java dynamic proxy implements Advised
- Not knowing a frozen proxy rejects advisor changes