skip to content

What is the Advised interface and what can you do by casting a live Spring AOP proxy to it?

level: middleimportance: should knowfreq 40%

answer

  1. every Spring proxy castable to Advised
  2. getAdvisors() = Advisor[] = pointcut + advice
  3. add/remove advisor at runtime, chain cache invalidated
  4. frozen -> AopConfigException on mutation
  5. getTargetSource / setTargetSource

basics

~20 s

Advised 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
java
// 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

for a junior

Know Advised lets you read getAdvisors() off a proxy.

for a middle

Explain runtime add/remove of advisors and the frozen restriction.

for a senior

Discuss chain caching/invalidation, thread-safety of live reconfiguration, and AopProxyUtils.ultimateTargetClass.

for a principal

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

context