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?
answer
- before / after-returning / after-throwing / after(finally) / around
- returning= and throwing= bind value/exception
- named <aop:pointcut> + pointcut-ref for reuse
- args() + arg-names to bind parameters
- around needs ProceedingJoinPoint + proceed()
basics
~10 sInside 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 sYou 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// 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
List the five advice element names and know method= points at the POJO method.
Correctly use pointcut-ref for reuse, and returning/throwing to bind results; know after vs after-returning.
Explain args()/arg-names binding, ordering within vs across aspects, and self-invocation bypassing the proxy.
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).