What is the difference between JoinPoint.getTarget() and JoinPoint.getThis()?
answer
- target = real bean, this = proxy
- JDK proxy vs CGLIB subclass
- self-invocation bypasses proxy = getThis skipped
- log getTarget().getClass() for real name
- getThis != getTarget in Spring AOP
basics
~20 sgetTarget() returns the real, un-proxied bean instance. getThis() returns the AOP proxy Spring created around it. They're usually different objects; the proxy is what other beans actually call, and the target holds your business logic.
solid answer
~40 sgetTarget() returns the target object — your actual bean instance with the business code. getThis() returns the proxy object Spring wove the advice into. With Spring AOP they are normally two distinct references: callers hold the proxy (getThis), and the proxy delegates to the target (getTarget). The concrete proxy type depends on the strategy: a JDK dynamic proxy (getThis is an interface-implementing proxy) when the bean has interfaces and interface-proxying is used, or a CGLIB proxy (getThis is a generated subclass of the target class) otherwise. This distinction explains the classic self-invocation limitation: when the target calls its own method via 'this', it bypasses the proxy (getThis), so no advice fires. For logging you usually want getTarget().getClass() to see the real class; getThis().getClass() would show the proxy's synthetic class name.
code
java · 18 linesimport org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class IdentityAspect {
@Before("execution(* com.katajob.service..*(..))")
public void show(JoinPoint jp) {
Object target = jp.getTarget(); // real bean, e.g. OrderServiceImpl
Object proxy = jp.getThis(); // proxy, e.g. OrderServiceImpl$$SpringCGLIB$$0
System.out.println("target class = " + target.getClass().getName());
System.out.println("proxy class = " + proxy.getClass().getName());
System.out.println("same object? = " + (target == proxy)); // false in Spring AOP
}
}go deeper
Know target = real bean, this = proxy.
Name JDK vs CGLIB and that they're different objects.
Tie getThis/getTarget to the self-invocation limitation and AopContext.currentProxy().
Contrast proxy-based vs weaving semantics and reason about when identity converges.
**Proxy model recap.** Spring AOP is proxy-based. Your bean (the *target*) is wrapped by a generated *proxy*. Other beans are injected with the proxy, so every external call goes proxy -> advice -> target. Two proxy strategies exist: **JDK dynamic proxies** (implement the bean's interfaces; require an interface) and **CGLIB proxies** (a runtime-generated subclass of the target class; the default when no interface, or when `proxyTargetClass=true`). **The two methods.** - **`getTarget()`** — the *target* instance: your real object, the one holding the actual method implementations and field state. Its class is your class (e.g. `OrderServiceImpl`). - **`getThis()`** — the *proxy* instance: the object Spring created to intercept calls. Its class is a synthetic type — a CGLIB subclass like `OrderServiceImpl$$SpringCGLIB$$0`, or a JDK proxy class like `com.sun.proxy.$ProxyNN`. **Why they differ.** In standard Spring AOP the advice lives on the proxy, and the proxy *delegates* to a separate target instance. So `getThis() != getTarget()` (different references, different classes). (With AspectJ *weaving* — LTW/CTW rather than Spring proxies — advice is woven directly into the class and `getThis()` and `getTarget()` can be the same object, but that's a different mechanism from Spring's default proxying.) **Practical consequences:** - **Logging the real class:** use `getTarget().getClass().getName()`; `getThis().getClass()` leaks the proxy's ugly synthetic name. - **Self-invocation gotcha:** inside the target, `this` is the target (== getTarget()), **not** the proxy (getThis()). So a method calling another `@Transactional`/advised method on `this` skips the proxy and the advice never runs. The fix is to call through the proxy, restructure into another bean, or use `AopContext.currentProxy()` (which returns getThis()). - **Identity checks:** never assume `getThis() == getTarget()` in Spring AOP; they are distinct. - **instanceof:** `getTarget()` is an instance of your class; `getThis()` is an instance of your interface (JDK proxy) or a subclass of your class (CGLIB). **When to use which.** Use `getTarget()` when you want the real bean/class for logging, reflection, or reading target state. Use `getThis()` when you specifically need the proxy — e.g. to re-enter the AOP chain, mirroring `AopContext.currentProxy()`.
- Why does self-invocation skip advice, and how does getThis() relate?Inside the target, 'this' is the target instance (getTarget()), not the proxy (getThis()). Calls on 'this' don't pass through the proxy, so no advice runs. Calling via AopContext.currentProxy() (== getThis()) or splitting into another bean restores it.
- When could getThis() and getTarget() be the same object?Under AspectJ weaving (compile-time or load-time), advice is woven into the class itself rather than a separate proxy, so both can reference the same instance. Not the case with Spring's default proxy-based AOP.
saying these in an interview costs you the question
- Saying getThis() returns the target and getTarget() the proxy (reversed)
- Assuming getThis() == getTarget() in Spring AOP
- Believing self-invoked advised methods still get advised
- Using getThis().getClass() to log the 'real' class name