Static vs Dynamic Proxy in Java: Implementation, Execution Results, and Comparison
This article explains the differences between static and dynamic proxies in Java, provides complete code examples for static proxy, JDK native dynamic proxy, and CGLib dynamic proxy, shows their execution results, and compares their usage scenarios, especially in backend development.
1. Static Proxy vs Dynamic Proxy
Proxy classes can enhance the methods of a target object. They are divided into static proxies, which require a manually written proxy class, and dynamic proxies, which are generated at runtime.
1.1 Static Proxy
Static proxy: the source code must declare a proxy class.
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 byte‑code generation to create a subclass (the proxy class) and its instance at runtime, allowing non‑intrusive enhancement of code.
Two main implementations:
JDK native dynamic proxy
CGLib dynamic proxy
2.1 JDK Native Dynamic Proxy
The proxy class and the target class must implement the same interface; only methods declared in the interface can be proxied.
2.1.1 Proxy
java.lang.reflect.Proxy is the base class for all dynamic proxies. The static method newProxyInstance() creates the proxy class and its instance.
2.1.2 InvocationHandler
Each proxy instance is associated with an InvocationHandler . Method calls on the proxy are forwarded to the handler's invoke method.
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 byte‑code generation library based on ASM. It creates a subclass of the target class at runtime to achieve proxying.
2.2.1 Enhancer
Enhancer specifies the target object to proxy. Calling create() returns the proxy instance. Method calls on non‑final methods are intercepted by a MethodInterceptor .
2.2.2 MethodInterceptor
The interceptor’s intercept method receives the method invocation, allowing pre‑ and post‑processing.
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 o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
doBefore();
Object result = methodProxy.invoke(target, objects);
doAfter();
return result;
}
}Execution result:
[Proxy]一些前置处理
【向数据库中插入数据】name:RyanLee,pwd:123
[Proxy]一些后置处理2.3 Comparison
The biggest difference is that JDK dynamic proxy requires the target to implement an interface, while CGLib proxies by subclassing the concrete class, allowing it to proxy classes without interfaces. Spring’s default proxy mechanism uses JDK dynamic proxy, but can be switched to CGLib.
Feel free to discuss, ask questions, or share your own experiences.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
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.