Understanding Spring AOP: Proxy Patterns, Static and Dynamic Proxies with JDK and CGLIB
This article explains the core concepts of Spring AOP, the proxy design pattern, and provides detailed Java examples of static proxy, JDK dynamic proxy, and CGLIB dynamic proxy, helping readers answer common interview questions and understand how Spring chooses the appropriate proxy implementation.
Spring AOP is a core technology frequently asked in interviews; this article summarizes its key points, starting with common interview questions such as the design pattern used by Spring AOP, the difference between static and dynamic proxies, and how to implement them.
What is Spring AOP? AOP (Aspect‑Oriented Programming) separates cross‑cutting concerns using the proxy pattern, similar to a celebrity delegating tasks to assistants. In code, a proxy controls method invocation before and after the actual business logic.
Proxy Design Pattern defines an abstract role implemented by both a real subject and a proxy subject. The proxy can add pre‑ and post‑processing while delegating the core operation to the real subject.
Static Proxy Example
/**
* Star interface
*/
public interface Star {
void sing();
}
/**
* RealStar implements Star
*/
public class RealStar implements Star {
@Override
public void sing() {
System.out.println("明星本人开始唱歌……");
}
}
/**
* ProxyStar implements Star and holds a reference to a real Star
*/
public class ProxyStar implements Star {
private Star star;
public ProxyStar(Star star) { this.star = star; }
@Override
public void sing() {
System.out.println("代理先进行谈判……");
this.star.sing();
System.out.println("演出完代理去收钱……");
}
}
/**
* Client test
*/
public class Client {
public static void main(String[] args) {
Star realStar = new RealStar();
Star proxy = new ProxyStar(realStar);
proxy.sing();
}
}The static proxy clearly separates pre‑ and post‑logic from the core sing method.
JDK Dynamic Proxy
/**
* Dynamic proxy handler
*/
public class JdkProxyHandler {
private Object realStar;
public JdkProxyHandler(Star star) { this.realStar = star; }
public Object getProxyInstance() {
return Proxy.newProxyInstance(
realStar.getClass().getClassLoader(),
realStar.getClass().getInterfaces(),
(proxy, method, args) -> {
System.out.println("代理先进行谈判……");
Object result = method.invoke(realStar, args);
System.out.println("演出完代理去收钱……");
return result;
});
}
}
/**
* Client test for JDK proxy
*/
public class Client {
public static void main(String[] args) {
Star realStar = new RealStar();
Star proxy = (Star) new JdkProxyHandler(realStar).getProxyInstance();
proxy.sing();
}
}JDK dynamic proxy works only for interfaces; it reduces boilerplate by generating the proxy class at runtime.
CGLIB Dynamic Proxy
/**
* CGLIB proxy handler implementing MethodInterceptor
*/
public class CglibProxyHandler implements MethodInterceptor {
private Object target;
public Object getProxyInstance(final Object target) {
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("代理先进行谈判……");
Object result = methodProxy.invokeSuper(obj, args);
System.out.println("演出完代理去收钱……");
return result;
}
}
/**
* Client test for CGLIB proxy
*/
public class Client {
public static void main(String[] args) {
Star realStar = new RealStar();
Star proxy = (Star) new CglibProxyHandler().getProxyInstance(realStar);
proxy.sing();
}
}CGLIB creates a subclass of the target class, allowing proxying of classes without interfaces, but it cannot proxy final classes or methods.
Spring AOP Proxy Selection
Spring decides which proxy mechanism to use based on configuration flags ( isOptimize , isProxyTargetClass ) and whether the target class implements any interfaces. If an interface is present, Spring defaults to JDK dynamic proxy; otherwise it falls back to CGLIB.
In summary, static proxy is simple and explicit, JDK dynamic proxy is interface‑based and lightweight, while CGLIB offers higher performance for class‑based proxies at the cost of longer creation time and inability to proxy final members.
Java Captain
Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.