Fundamentals 8 min read

Understanding the Proxy Pattern: Static and Dynamic Proxies in Java

This article explains the GoF Proxy pattern, illustrates static proxy implementation, and details both JDK dynamic proxy and cglib dynamic proxy techniques in Java with complete code examples and a comparison of their characteristics and usage scenarios.

Full-Stack Internet Architecture
Full-Stack Internet Architecture
Full-Stack Internet Architecture
Understanding the Proxy Pattern: Static and Dynamic Proxies in Java

The Proxy pattern is widely used, especially in Java frameworks like Spring, which employ both JDK dynamic proxies and CGLIB proxies; this article focuses on the classic GoF Proxy pattern and demonstrates its implementation in Java.

Roles in the pattern: Subject (abstract role), RealSubject (concrete implementation), and Proxy (the surrogate that controls access to the real subject).

Interface definition for Subject :

public interface Subject {
    void request();
}

Concrete implementation RealSubject :

public class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("真实的请求RealSubject");
    }
}

Static proxy class Proxy that adds pre‑ and post‑processing:

public class Proxy implements Subject {
    private RealSubject realSubject = null;
    public Proxy() {
        this.realSubject = new RealSubject();
    }
    @Override
    public void request() {
        doBefore();
        realSubject.request();
        doAfter();
    }
    private void doBefore() {
        System.out.println("-------do before------");
    }
    private void doAfter() {
        System.out.println("-------do after-------");
    }
}

Client usage demonstrates a simple static proxy:

public class Client {
    public static void main(String[] args) {
        Proxy proxy = new Proxy();
        proxy.request();
    }
}

Static proxies require a separate proxy class for each real subject and need the subject to be defined via an interface or abstract class, which can become cumbersome when the interface changes.

Dynamic Proxy (JDK) : generated at runtime using Java reflection, eliminating the need to write proxy source code. It requires the target class to implement an interface and an InvocationHandler to define the additional behavior.

Example interfaces and classes:

public interface IFangDong {
    void hire(String area);
}
public class FangDong implements IFangDong {
    @Override
    public void hire(String area) {
        System.out.println(area);
    }
}

Invocation handler implementation:

public class FangDongProxy implements InvocationHandler {
    private Object target;
    public void setTarget(Object target) {
        this.target = target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("必须租给程序员~~因为他们人傻钱多");
        return method.invoke(target, args);
    }
    public Object creatProxyedObj() {
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }
}

Client code using the JDK dynamic proxy:

public class Client {
    public static void main(String[] args) {
        IFangDong fd = new FangDong();
        FangDongProxy proxy = new FangDongProxy();
        proxy.setTarget(fd);
        IFangDong fangDong = (IFangDong) proxy.creatProxyedObj();
        fangDong.hire("我有130平大房子出租~~");
    }
}

CGLIB Dynamic Proxy : does not require the target to implement an interface; it creates a subclass of the target class at runtime. It needs the third‑party cglib library.

CGLIB proxy implementation:

public class FangDongCglibProxy implements MethodInterceptor {
    public Object CreatProxyedObj(Class
clazz) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        return enhancer.create();
    }
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("FangDongCglibProxy》》》必须租给程序员~~因为他们人傻钱多");
        return methodProxy.invokeSuper(obj, args);
    }
}

Client code using the CGLIB proxy:

public class Client {
    public static void main(String[] args) {
        FangDongCglibProxy proxy = new FangDongCglibProxy();
        FangDong fangDong = (FangDong) proxy.CreatProxyedObj(FangDong.class);
        fangDong.hire("我有130平大房子出租~~");
    }
}

In summary, JDK dynamic proxies work only with interfaces, while CGLIB can proxy concrete classes without interfaces, offering more flexibility at the cost of an additional library dependency.

design patternsJavaDynamic ProxyProxy PatternStatic ProxyCglibJDK Proxy
Full-Stack Internet Architecture
Written by

Full-Stack Internet Architecture

Introducing full-stack Internet architecture technologies centered on Java

0 followers
Reader feedback

How this landed with the community

login 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.