Understanding the Proxy Design Pattern in Java: Static, Dynamic, and CGLIB Implementations
This article explains the Proxy design pattern, covering its purpose, static, dynamic (JDK), and CGLIB implementations in Java, provides complete code examples, discusses advantages and disadvantages, and outlines typical use cases such as lazy initialization, access control, remote services, logging, and caching.
Basic Introduction
Proxy pattern is a structural design pattern that provides a surrogate or placeholder for another object to control access to it. It can be used for remote objects, expensive-to-create objects, or objects that need security control.
Problem
When a heavyweight object is needed only occasionally, creating it eagerly wastes resources; duplicating lazy‑initialization code across clients is error‑prone, especially when the original class is part of a third‑party library.
Solution
Introduce a proxy class that implements the same interface as the real service. The client works with the proxy, which creates the real object on demand and delegates all calls, allowing pre‑ and post‑processing such as logging, caching, or access checks.
Proxy Structure
Four participants: Service Interface, Service (real object), Proxy (holds a reference to Service and adds extra behavior), Client (uses the interface).
Static Proxy Example
public interface Internet {
void connectTo(String serverHost) throws Exception;
}
public class RealInternet implements Internet {
@Override
public void connectTo(String serverHost) throws Exception {
System.out.println("Connecting to " + serverHost);
}
}
public class ProxyInternet implements Internet {
private Internet internet;
private static List
bannedSites;
static {
bannedSites = new ArrayList<>();
bannedSites.add("bilibili.com");
bannedSites.add("youtube.com");
bannedSites.add("weibo.com");
bannedSites.add("qq.com");
}
public ProxyInternet(Internet internet) {
this.internet = internet;
}
@Override
public void connectTo(String serverhost) throws Exception {
if (bannedSites.contains(serverhost.toLowerCase())) {
throw new Exception("Access Denied:" + serverhost);
}
internet.connectTo(serverhost);
}
}
public class Client {
public static void main(String[] args) {
Internet internet = new ProxyInternet(new RealInternet());
try {
internet.connectTo("so.com");
internet.connectTo("qq.com");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}Dynamic Proxy (JDK) Example
public class ProxyFactory {
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
public Object getProxyInstance() {
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (bannedSites.contains(args[0].toString().toLowerCase())) {
throw new Exception("Access Denied:" + args[0]);
}
return method.invoke(target, args);
}
}
);
}
private static List
bannedSites;
static {
bannedSites = new ArrayList<>();
bannedSites.add("bilibili.com");
bannedSites.add("youtube.com");
bannedSites.add("weibo.com");
bannedSites.add("qq.com");
}
}CGLIB Proxy Example
public class ProxyFactory implements MethodInterceptor {
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("cglib proxy start");
Object result = method.invoke(target, objects);
System.out.println("cglib proxy end");
return result;
}
public Object getProxyInstance() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
}Typical Application Scenarios
Lazy initialization (virtual proxy)
Access control (protection proxy)
Remote service access (remote proxy)
Logging requests (logging proxy)
Caching results (cache proxy)
Smart reference for resource cleanup
Proxy Pattern in AOP
Spring AOP uses JDK dynamic proxies or CGLIB to create proxies for beans; AspectJ uses compile‑time static proxies. The choice is made by DefaultAopProxyFactory based on configuration.
References
https://refactoringguru.cn/design-patterns/proxy https://www.geeksforgeeks.org/proxy-design-pattern/
Full-Stack Internet Architecture
Introducing full-stack Internet architecture technologies centered on Java
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.