What do the perthis and pertarget aspect instantiation models do in Spring AOP, and how must the aspect bean be scoped?
answer
- perthis = per unique 'this'/proxy object
- pertarget = per unique target object
- MUST be prototype-scoped bean
- lazy: created on first matched join point
- Spring: NO percflow/pertypewithin
basics
~20 sperthis creates a new aspect instance for each unique object executing a matched join point (each unique 'this'/proxy); pertarget creates one per unique target object. Both are non-singleton, so the aspect bean must be declared with prototype scope so Spring can create multiple instances.
solid answer
~40 sSpring AOP supports two non-singleton AspectJ models beyond the default singleton: **perthis** and **pertarget**. You declare them in the annotation, e.g. `@Aspect("perthis(com.example.Pointcuts.serviceMethods())")`. With **perthis**, a separate aspect instance is created for each unique object that is `this` (the AOP proxy) at a matched join point; with **pertarget**, one per unique **target** object behind the proxy. In Spring AOP proxying, this practically means one aspect instance per advised bean, letting the aspect hold **per-object state** (counters, rate limiters). Crucially the aspect bean must be **prototype-scoped** so Spring can instantiate it repeatedly. Instances are created **lazily** on first matched join point for a given object. Note Spring does **not** support percflow, percflowbelow, or pertypewithin — only singleton, perthis, and pertarget.
code
java · 21 lines@Aspect("perthis(com.example.SystemArchitecture.businessService())")
@Component
@Scope("prototype") // REQUIRED: Spring must create one instance per object
public class PerObjectRateLimitAspect {
// Because a new aspect instance exists per advised object,
// this field is effectively per-object state (not global).
private int callsForThisObject = 0;
@Before("com.example.SystemArchitecture.businessService()")
public void beforeCall() {
callsForThisObject++; // isolated per advised bean
}
}
// Supporting pointcut holder:
// @Aspect
// class SystemArchitecture {
// @Pointcut("execution(* com.example.service..*(..))")
// public void businessService() {}
// }go deeper
Awareness that non-singleton aspect models exist is enough; details not expected.
Know perthis/pertarget give per-object state and require prototype scope.
Distinguish perthis vs pertarget, explain lazy creation and the prototype requirement, and know the unsupported models.
Weigh perthis/pertarget vs a keyed-map singleton for per-object state, reason about memory/lifecycle, and the this-vs-target distinction under proxy semantics.
**Recap of the default.** By default an aspect is a **singleton** — one shared instance for everything. The other models let the aspect keep state tied to individual advised objects. **perthis.** Declared as `@Aspect("perthis(<pointcut>)")`. A **new aspect instance is created for each unique object executing** a join point matched by the pointcut — i.e. per unique `this`. In Spring AOP, `this` at a join point is the **AOP proxy**, so you get one aspect instance per advised (proxied) object. The instance is created **lazily** the first time that particular object hits a matched join point, and it lives as long as that object does. **pertarget.** Declared as `@Aspect("pertarget(<pointcut>)")`. A **new aspect instance per unique target object** — the actual bean instance behind the proxy. In typical Spring AOP setups (singleton target beans, one proxy each) perthis and pertarget behave very similarly; the distinction matters more when `this` (proxy) and target differ, or under AspectJ semantics where `this` can be a caller. **Mandatory prototype scope.** Because these models require Spring to create **multiple** aspect instances, the aspect bean **must be declared with prototype scope** (`@Scope("prototype")` or `scope="prototype"`). A singleton-scoped bean cannot be instantiated per object, so the model would not work. This is the single most important practical rule and a frequent interview point. **Why use them.** When the cross-cutting concern needs **per-object state**: e.g. a per-service-instance call counter, a per-object circuit breaker / rate limiter, or accumulating metrics isolated per target. With a singleton aspect you'd have to build that isolation yourself (e.g. a `Map` keyed by object); perthis/pertarget give it to you structurally. **What Spring does NOT support.** AspectJ additionally defines **percflow**, **percflowbelow**, and **pertypewithin** instantiation models. **Spring AOP supports only singleton, perthis, and pertarget.** Claiming Spring supports percflow/pertypewithin is a red flag. **Pointcut in the model vs advice pointcuts.** The pointcut named inside `perthis(...)`/`pertarget(...)` governs *when a new aspect instance is created* (which objects get their own aspect); your advice methods still have their own pointcuts for *what they intercept*. **Lifecycle / memory considerations.** Since one aspect instance can exist per advised object, and instances are created lazily and retained, be mindful of memory if there are many distinct advised objects. For long-lived singleton service beans this is bounded and fine; for many short-lived proxied objects it can add overhead. **Gotchas.** - Forgetting `@Scope("prototype")` — the model silently won't behave as intended / bean creation fails to multiply. - Expecting perthis to give per-*invocation* isolation — it is per-*object*, not per-call. - Assuming these are common — they are relatively rare; most real aspects are singletons, and per-object state is often handled with a keyed map instead.
- You declared a perthis aspect but left it singleton-scoped. What is wrong?perthis/pertarget need Spring to create multiple aspect instances (one per object), which requires prototype scope. As a singleton the per-object instantiation cannot happen, so the intended per-object behavior is broken.
- Which AspectJ instantiation models does Spring AOP NOT support?percflow, percflowbelow, and pertypewithin. Spring AOP supports only singleton (default), perthis, and pertarget.
- Is perthis per-invocation or per-object?Per-object: one aspect instance per unique object executing the matched join point, created lazily on first match. It is not a fresh aspect per method call.
saying these in an interview costs you the question
- Saying perthis/pertarget work with a singleton-scoped aspect bean
- Claiming Spring supports percflow or pertypewithin
- Describing perthis as per-invocation rather than per-object
- Confusing perthis (per proxy/this) with pertarget (per target) and treating them as identical in all cases