Dynamic Proxy (JDK and CGLIB)
Dynamic Proxy (JDK and CGLIB)
JDK Dynamic Proxy
The JDK Dynamic Proxy is a built-in feature of the Java platform that allows you to create a proxy object that delegates method calls to a target object. The target object is usually an interface or a class that implements the methods you want to expose to the proxy.
To create a JDK Dynamic Proxy, you need to use the Proxy
class and pass in the interface or class that the proxy should implement, as well as the target object that the proxy should delegate method calls to. Here's an example:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 目标接口
public interface Person {
void sayHello();
}
// 目标类
public class RealPerson implements Person {
@Override
public void sayHello() {
System.out.println("Hello, I'm a real person.");
}
}
// InvocationHandler实现
public class MyInvocationHandler implements InvocationHandler {
private Object target;
public MyInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before method call");
Object result = method.invoke(target, args); // 调用实际对象方法
System.out.println("After method call");
return result;
}
}
// 客户端代码
public class JDKDynamicProxyExample {
public static void main(String[] args) {
Person realPerson = new RealPerson();
// 创建代理对象
Person proxyPerson = (Person) Proxy.newProxyInstance(
realPerson.getClass().getClassLoader(),
new Class<?>[]{Person.class},
new MyInvocationHandler(realPerson)
);
// 通过代理对象调用方法
proxyPerson.sayHello();
}
}
CGLIB Dynamic Proxy
CGLIB (Code Generation Library) is a library that allows you to create dynamic proxy objects at runtime. It generates the proxy class at runtime using a technique called byte code manipulation.
To create a CGLIB Dynamic Proxy, you need to use the Enhancer
class and pass in the class that the proxy should implement, as well as the target object that the proxy should delegate method calls to. Here's an example:
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
// 目标类
public class RealPerson {
public void sayHello() {
System.out.println("Hello, I'm a real person.");
}
}
// CGLIB代理处理器
public class MyMethodInterceptor implements MethodInterceptor {
private Object target;
public MyMethodInterceptor(Object target) {
this.target = target;
}
@Override
public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("Before method call");
Object result = proxy.invokeSuper(obj, args); // 调用目标对象的方法
System.out.println("After method call");
return result;
}
}
// 客户端代码
public class CGLIBDynamicProxyExample {
public static void main(String[] args) {
RealPerson realPerson = new RealPerson();
// 创建CGLIB代理对象
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(RealPerson.class);
enhancer.setCallback(new MyMethodInterceptor(realPerson));
// 创建代理对象
RealPerson proxyPerson = (RealPerson) enhancer.create();
// 通过代理对象调用方法
proxyPerson.sayHello();
}
}
JDK Dynamic Proxy vs. CGLIB Dynamic Proxy
1. Comparison
Feature | JDK Dynamic Proxy | CGLIB Dynamic Proxy |
---|---|---|
Proxy Mechanism | Based on interface implementation | Based on subclass generation |
Target Requirement | Target class must implement an interface | Target class does not need to implement an interface |
Performance | Better, as it only uses reflection | Slightly lower, as it creates a subclass and overrides methods |
Limitations | Cannot proxy classes without interfaces | Cannot proxy final classes and final methods |
Suitable Scenarios | When the target class implements an interface | When the target class does not implement an interface or requires subclass-based proxying |
2. Summary
JDK Dynamic Proxy:
- Based on interface implementation, can only proxy interfaces.
- Performs well and is suitable for most scenarios where interfaces are available.
CGLIB Dynamic Proxy:
- Based on class inheritance, can proxy classes without interfaces.
- Slightly lower performance due to subclass creation, but useful when the target class lacks an interface.
Which One to Choose?
- If the target class implements an interface, prefer JDK Dynamic Proxy for better performance.
- If the target class does not implement an interface, use CGLIB Dynamic Proxy.