Why Spring AOP Doesn’t Apply to ‘this’ Calls and How to Fix It

This article explains why Spring AOP proxies are not applied when a bean invokes its own methods via the this reference, compares JDK and CGLIB proxy mechanisms, and shows how to enable proxy exposure or use AopContext to achieve the desired AOP behavior.

JavaEdge
JavaEdge
JavaEdge
Why Spring AOP Doesn’t Apply to ‘this’ Calls and How to Fix It

Problem Overview

Spring AOP weaves aspect code into bean methods at runtime using proxies. When a bean calls its own method via this, the call bypasses the proxy, so the advice is not executed.

Example Scenario

A CouponService class provides a deposit() method. An @Around advice is defined to record the execution time of pay(). The controller invokes deposit() through the injected bean, but the internal call uses this.deposit(), which refers to the plain target object, so the advice never runs.

Why this Bypasses the Proxy

The this reference points to the original CouponService instance created by the developer, not the Spring‑generated proxy.

The bean injected into other components is a proxy; only calls made on that proxy trigger the aspect logic.

Proxy Creation Mechanisms

JDK dynamic proxy : works only for beans that implement an interface.

CGLIB proxy : creates a subclass of the concrete class and overrides its methods, allowing proxying of classes without interfaces.

Enabling AOP (Non‑Spring‑Boot Applications)

Add the AOP starter dependencies and annotate a configuration class with @EnableAspectJAutoProxy. This registers AspectJAutoProxyRegistrar via the ImportBeanDefinitionRegistrar interface, which prepares the necessary infrastructure beans.

Bean Post‑Processing and Proxy Wrapping

During bean initialization, AnnotationAwareAspectJAutoProxyCreator (a BeanPostProcessor) runs after the original bean is instantiated. Its postProcessAfterInitialization method invokes wrapIfNecessary. If the bean matches any AOP pointcut, a proxy (JDK or CGLIB) is created and returned as the bean instance.

AOP proxy creation flow
AOP proxy creation flow

Solutions for Self‑Invocation

To make internal method calls go through the proxy, use one of the following approaches:

Inject the bean into itself so that the injected reference is the proxy, e.g.

@Autowired
private CouponService self;

public void someMethod(){
    self.deposit(); // goes through proxy
}

Obtain the current proxy from AopContext. This requires exposing the proxy:

@EnableAspectJAutoProxy(exposeProxy = true)

Then invoke the method via the proxy:

AopContext.currentProxy().deposit();

Practical Configuration

When using AopContext, ensure the @EnableAspectJAutoProxy annotation includes exposeProxy = true. After applying either self‑injection or proxy exposure, the deposit() call is routed through the Spring proxy and the @Around advice correctly records execution time.

Self‑injection example
Self‑injection example
AopContext usage example
AopContext usage example
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaProxyaopspringJDKdependency-injectioncglib
JavaEdge
Written by

JavaEdge

First‑line development experience at multiple leading tech firms; now a software architect at a Shanghai state‑owned enterprise and founder of Programming Yanxuan. Nearly 300k followers online; expertise in distributed system design, AIGC application development, and quantitative finance investing.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.