Static vs Dynamic Proxy in Java: When and How to Use Each

This article explains the differences between static and dynamic proxies in Java, demonstrates how to implement static proxies, JDK dynamic proxies, and CGLib proxies with complete code examples, and compares their advantages, limitations, and typical use cases in backend development.

Architect's Guide
Architect's Guide
Architect's Guide
Static vs Dynamic Proxy in Java: When and How to Use Each

1. Static Proxy vs Dynamic Proxy

Proxy classes can enhance the methods of the target object. They are divided into static proxies and dynamic proxies.

1.1 Static Proxy

Static proxy: the proxy class must be declared in source code.

public class TestStaticProxy {
    public static void main(String[] args) {
        IRegisterService iRegisterService = new RegisterServiceImpl();
        IRegisterService proxy = new RegisterServiceProxy(iRegisterService);
        proxy.register("RyanLee", "123");
    }
}

interface IRegisterService {
    void register(String name, String pwd);
}

class RegisterServiceImpl implements IRegisterService {
    @Override
    public void register(String name, String pwd) {
        System.out.println(String.format("【向数据库中插入数据】name:%s,pwd:%s", name, pwd));
    }
}

class RegisterServiceProxy implements IRegisterService {
    IRegisterService iRegisterService;
    public RegisterServiceProxy(IRegisterService iRegisterService) {
        this.iRegisterService = iRegisterService;
    }
    @Override
    public void register(String name, String pwd) {
        System.out.println("[Proxy]一些前置处理");
        System.out.println(String.format("[Proxy]打印注册信息:姓名:%s,密码:%s", name, pwd));
        iRegisterService.register(name, pwd);
        System.out.println("[Proxy]一些后置处理");
    }
}

Execution result:

[Proxy]一些前置处理
[Proxy]打印注册信息:姓名:RyanLee,密码:123
【向数据库中插入数据】name:RyanLee,pwd:123
[Proxy]一些后置处理

1.2 Dynamic Proxy

Dynamic proxy: no need to declare a proxy class. It uses reflection and bytecode generation to create a subclass of the specified interface or class at runtime, allowing non‑intrusive enhancement of code.

Dynamic proxy can be implemented in two main ways:

JDK native dynamic proxy

CGLib dynamic proxy (Code Generation Library)

2. Implementation of Dynamic Proxy

2.1 JDK Native Dynamic Proxy

The dynamic proxy class and the target class must implement the same interface. JDK dynamic proxy can only proxy methods declared in the interface.

2.1.1 Proxy

java.lang.reflect.Proxy

is the parent class of all dynamic proxies. It creates proxy class objects and instances via the static method newProxyInstance().

2.1.2 InvocationHandler

Each dynamic proxy instance is associated with an InvocationHandler. Method calls on the proxy are forwarded to the handler's invoke method.

2.1.3 Example

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class TestJdkDynamicProxy {
    public static void main(String[] args) {
        IRegisterService iRegisterService = new RegisterServiceImpl();
        InsertDataHandler insertDataHandler = new InsertDataHandler();
        IRegisterService proxy = (IRegisterService) insertDataHandler.getProxy(iRegisterService);
        proxy.register("RyanLee", "123");
    }
}

class InsertDataHandler implements InvocationHandler {
    Object obj;
    public Object getProxy(Object obj) {
        this.obj = obj;
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        doBefore();
        Object result = method.invoke(obj, args);
        doAfter();
        return result;
    }
    private void doBefore() {
        System.out.println("[Proxy]一些前置处理");
    }
    private void doAfter() {
        System.out.println("[Proxy]一些后置处理");
    }
}

Execution result:

[Proxy]一些前置处理
【向数据库中插入数据】name:RyanLee,pwd:123
[Proxy]一些后置处理

2.2 CGLib Dynamic Proxy

CGLib (Code Generation Library) is a bytecode generation library based on ASM. It creates proxies by subclassing the target class.

2.2.1 Enhancer

Enhancer specifies the target object to proxy. The create method returns the proxy instance. Method calls on non‑final methods are intercepted by MethodInterceptor.

2.2.2 MethodInterceptor

The interceptor’s intercept method receives the method call, allowing pre‑ and post‑processing.

2.2.3 Example

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;

public class TestCGLibDynamicProxy {
    public static void main(String[] args) {
        IRegisterService iRegisterService = new RegisterServiceImpl();
        InsertDataInterceptor interceptor = new InsertDataInterceptor();
        RegisterServiceImpl proxy = (RegisterServiceImpl) interceptor.getProxy(iRegisterService);
        proxy.register("RyanLee", "123");
    }
}

class InsertDataInterceptor implements MethodInterceptor {
    Object target;
    public Object getProxy(Object target) {
        this.target = target;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(this.target.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }
    private void doBefore() {
        System.out.println("[Proxy]一些前置处理");
    }
    private void doAfter() {
        System.out.println("[Proxy]一些后置处理");
    }
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        doBefore();
        Object result = methodProxy.invoke(target, args);
        doAfter();
        return result;
    }
}

Execution result:

[Proxy]一些前置处理
【向数据库中插入数据】name:RyanLee,pwd:123
[Proxy]一些后置处理

2.3 JDK Dynamic Proxy vs CGLib Dynamic Proxy

The main differences are:

JDK dynamic proxy requires the target to implement an interface; it can only proxy interface methods.

CGLib creates a subclass of the target class, allowing proxy of concrete classes without interfaces.

Spring’s default proxy mechanism uses JDK dynamic proxies; it can be switched to CGLib by changing configuration, and it is generally recommended not to place Spring annotations on interfaces when CGLib is needed.

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.

JavaProxyBackend DevelopmentJDKDynamic ProxyStatic Proxycglib
Architect's Guide
Written by

Architect's Guide

Dedicated to sharing programmer-architect skills—Java backend, system, microservice, and distributed architectures—to help you become a senior architect.

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.