skip to content

Schema-Based (XML) AOP Configuration

The <aop:config> XML namespace does everything the annotations do, and <aop:advisor> can advise plain beans without annotating anything. You mostly need it to read legacy configuration, which is a realistic interview scenario.

part ofSpring Frameworkoverview, primer and where to startread it →
on this pageshow

questions

5

Walk through declaring an aspect in XML with <aop:aspect>, <aop:pointcut>, and the advice elements. How do you bind advice methods and reuse a named pointcut?

level: middleimportance: must knowfreq 45%

answer

  1. before / after-returning / after-throwing / after(finally) / around
  2. returning= and throwing= bind value/exception
  3. named <aop:pointcut> + pointcut-ref for reuse
  4. args() + arg-names to bind parameters
  5. around needs ProceedingJoinPoint + proceed()

basics

~10 s

Inside aop:config, add <aop:aspect ref="bean">. Declare a named <aop:pointcut id="..." expression="..."/>, then attach advice like <aop:before pointcut-ref="..." method="..."/>. Each advice element names the POJO method and the pointcut to match.

solid answer

~40 s

You nest an <aop:aspect ref="backingBean"> in <aop:config>. Pointcuts are declared either inline (a pointcut attribute on the advice) or as a reusable named <aop:pointcut id="svc" expression="execution(* com.app.service..*(..))"/> referenced via pointcut-ref. Advice elements are <aop:before>, <aop:after-returning>, <aop:after-throwing>, <aop:after> (finally), and <aop:around>; each carries method (the POJO method name) plus pointcut or pointcut-ref. <aop:after-returning> and <aop:after-throwing> bind the value/exception through returning and throwing attributes. To pass matched arguments into the method, use args() in the expression and list parameter names in arg-names, since XML can't always read them from bytecode. A named pointcut declared at the top of <aop:config> is shared across aspects; one nested in an aspect is scoped to it.

code

java · 30 lines
java
// Backing POJO with plain advice methods.
package com.app;
import org.aspectj.lang.JoinPoint;

public class TxLogAspect {
    public void before(long accountId, double amount) {   // bound via args()/arg-names
        System.out.println("transfer of " + amount + " from " + accountId);
    }
    public void onSuccess(Object result) {                 // bound via returning="result"
        System.out.println("returned: " + result);
    }
    public void onError(Throwable ex) {                    // bound via throwing="ex"
        System.out.println("failed: " + ex.getMessage());
    }
}

/*
<aop:config>
    <aop:pointcut id="transferOp"
        expression="execution(* com.app.AccountService.transfer(..)) and args(accountId,amount)"/>

    <aop:aspect ref="txLogAspect" order="1">
        <aop:before          pointcut-ref="transferOp" method="before"
                             arg-names="accountId,amount"/>
        <aop:after-returning pointcut-ref="transferOp" method="onSuccess" returning="result"/>
        <aop:after-throwing  pointcut-ref="transferOp" method="onError"   throwing="ex"/>
    </aop:aspect>
</aop:config>
<bean id="txLogAspect" class="com.app.TxLogAspect"/>
*/

go deeper

for a junior

List the five advice element names and know method= points at the POJO method.

for a middle

Correctly use pointcut-ref for reuse, and returning/throwing to bind results; know after vs after-returning.

for a senior

Explain args()/arg-names binding, ordering within vs across aspects, and self-invocation bypassing the proxy.

for a principal

Reason about pointcut scoping/visibility, why bytecode parameter names force arg-names, and the runtime-proxy join-point limits vs full AspectJ.

**Structure.** A schema aspect has three moving parts: the container `<aop:config>`, the aspect grouping `<aop:aspect>`, and the advice/pointcut elements inside it. **`<aop:aspect>`.** `<aop:aspect id="logging" ref="loggingBean">` associates a group of advice with a **backing bean** (`ref` points to a normal `<bean>`). The advice methods live on that bean. An optional `order` attribute sets precedence relative to other aspects/advisors (lower value = higher precedence = runs first on the way in). **Pointcuts — two forms.** 1. *Inline:* put the expression directly on the advice element: `<aop:before pointcut="execution(* com.app..*(..))" method="m"/>`. 2. *Named/reusable:* `<aop:pointcut id="serviceOps" expression="execution(* com.app.service..*(..))"/>` then reference with `pointcut-ref="serviceOps"`. A named pointcut declared **directly under `<aop:config>`** (before any aspect) is visible to all aspects and advisors; one declared **inside an `<aop:aspect>`** is scoped to that aspect. Named pointcuts avoid repeating expressions and give them a readable label. **The advice elements** (each takes `method` = the POJO method name, plus `pointcut` or `pointcut-ref`): - `<aop:before>` — runs before the join point. - `<aop:after-returning>` — runs after normal (non-exceptional) return. `returning="result"` binds the returned value to a method parameter named `result`; if the actual return type doesn't match the parameter type, the advice simply doesn't fire. - `<aop:after-throwing>` — runs when the method throws. `throwing="ex"` binds the exception to a parameter named `ex`; typing the parameter (e.g. `DataAccessException ex`) narrows it to matching throwables. - `<aop:after>` — the *finally* advice; runs whether the method returns or throws. - `<aop:around>` — the most powerful; its method must take a `ProceedingJoinPoint` as the first parameter and call `proceed()` to invoke the target (and can inspect/replace args and return value). **Argument binding — `args()` and `arg-names`.** To receive the target method's arguments, use the `args(...)` designator in the pointcut and give the *same* names to the advice method's parameters. Because compiled bytecode may lack parameter-name info (depending on `-parameters`/debug flags), the `arg-names` attribute explicitly lists the parameter names in order so Spring can map `args(accountId)` to the `accountId` method parameter. Example: `<aop:before pointcut="execution(* transfer(..)) and args(accountId,amount)" method="check" arg-names="accountId,amount"/>`. Order matters; names must match the method signature. **Access to the join point.** Any advice method can declare a first parameter of type `org.aspectj.lang.JoinPoint` (or `ProceedingJoinPoint` for `<aop:around>`) to read `getArgs()`, `getSignature()`, `getTarget()`, etc. — no XML attribute needed for that. **Gotchas.** - `<aop:after>` runs on *both* paths — don't put success-only logic there; use `after-returning`. - Ordering of multiple advice *within the same aspect*: Spring runs them by declaration order (since 5.2.7); across aspects, use `order`. - Proxying is runtime, so **self-invocation** (a method in the target calling another advised method via `this`) bypasses the proxy and the advice — unavoidable without `expose-proxy` + `AopContext.currentProxy()`. - Only **method-execution** join points are supported (Spring AOP), regardless of what AspectJ expression you write — designators like `call()`, `get()`, `set()` aren't supported by Spring's proxy runtime.

  • What is the difference between <aop:after> and <aop:after-returning>?
    <aop:after> is 'after finally' — it runs whether the method returns normally or throws. <aop:after-returning> runs only on a normal (non-exceptional) return and can bind the returned value via the returning attribute.
  • Why might you need the arg-names attribute?
    When binding parameters with args(), Spring maps pointcut parameter names to advice-method parameter names. If the class wasn't compiled with parameter-name info (e.g. no -parameters/debug flag), Spring can't infer names from bytecode, so arg-names lists them explicitly and in order.
  • Where should a named pointcut go if two different aspects need it?
    Declare it directly under <aop:config> (before the aspects), not inside an <aop:aspect>. Top-level named pointcuts are shared; ones nested inside an aspect are visible only to that aspect.

saying these in an interview costs you the question

  • Claiming <aop:after> runs only on success (it runs on both success and exception).
  • Putting the return-value binding on <aop:before> or forgetting the returning/throwing attribute names must match method parameter names.
  • Thinking Spring AOP can match field access or method 'call' join points (only method-execution join points on Spring beans).

context

open as a page

What is schema-based (XML) AOP configuration in Spring, and what does the <aop:config> element do?

level: juniorimportance: should knowfreq 35%

basics

~10 s

It configures aspects in XML instead of with @Aspect annotations. The aop:config element (from the aop namespace) holds aspect definitions; Spring reads it and wraps matching beans in proxies that run your advice.

open as a page

How do you write around advice in schema-based AOP, and what must the advice method's signature look like?

level: middleimportance: should knowfreq 33%

basics

~10 s

Use <aop:around pointcut="..." method="..."/>. The referenced POJO method must take a ProceedingJoinPoint as its first parameter and call proceed() to run the target. Its return value becomes the method's result.

open as a page

What is <aop:advisor> and how does it differ from <aop:aspect>? When would you wire a plain bean as an advisor?

level: seniorimportance: should knowfreq 40%

basics

~20 s

aop:advisor pairs a pointcut with a reusable advice bean that already implements a Spring Advice interface (like MethodInterceptor). aop:aspect instead groups multiple advice methods on a plain POJO. Advisors are how tx:advice transactions get applied.

open as a page

Compare schema-based XML AOP with @AspectJ annotation-based AOP. What are the semantic differences, limitations, and when would you deliberately choose XML?

level: principalimportance: should knowfreq 30%

basics

~20 s

Both are proxy-based Spring AOP using the same AspectJ pointcut language and produce identical proxies. XML keeps advice metadata outside the class (good for third-party beans or externalized config); annotations keep it cohesive. XML supports only singleton aspects; @AspectJ also supports perthis/pertarget.

open as a page