返回
大招聚齐,代理之道无处不在之静态代理、动态代理、cglib动态代理
后端
2024-01-08 10:12:52
深度探究代理模式之精髓
代理模式是一种设计模式,允许您创建一个代表另一个对象的类。代理可以拦截并控制对原对象的访问,在不改变原对象自身的情况下,为原对象提供额外的功能或行为。
静态代理:简便易用,适时相伴
静态代理通过实现目标对象的接口,创建一个代理对象来代替原对象。代理对象与原对象之间存在一对一的对应关系。
优点:
- 实现简单,结构清晰,易于理解和维护。
缺点:
- 需要为每个原对象创建代理对象,代码量会增加。
- 代理对象与原对象紧密耦合,当原对象发生变化时,代理对象也需要相应地修改。
JDK动态代理:灵活多变,游刃有余
JDK动态代理是一种通过反射机制创建代理对象的动态代理技术。它无需实现目标对象的接口,而是通过反射机制创建代理对象,并使用InvocationHandler接口来控制对原对象的调用。
优点:
- 无需实现目标对象的接口,更加灵活。
- 代理对象与原对象松散耦合,当原对象发生变化时,代理对象无需修改。
- 支持对接口和类的代理。
缺点:
- 性能开销比静态代理更大。
- 只能代理接口,不能代理类。
Cglib动态代理:以类为本,无拘无束
Cglib动态代理是一种基于字节码生成技术的动态代理技术。它无需实现目标对象的接口,而是通过字节码生成技术创建一个代理类,并使用MethodInterceptor接口来控制对原对象的方法调用。
优点:
- 可以代理类,也可以代理接口。
- 性能开销比JDK动态代理更小。
缺点:
- 实现更复杂,学习难度更大。
- 不支持对final类和方法的代理。
三种代理模式之适用场景
- 静态代理: 适用于原对象不需要频繁变化,代理对象与原对象紧密耦合的情况。
- JDK动态代理: 适用于原对象需要频繁变化,代理对象与原对象松散耦合的情况。
- Cglib动态代理: 适用于需要对类进行代理的情况,或需要更高性能的代理的情况。
技术指南:代码示例与实践指导
静态代理代码示例:
public class StaticProxy implements Subject {
private Subject realSubject;
public StaticProxy(Subject realSubject) {
this.realSubject = realSubject;
}
@Override
public void request() {
System.out.println("Before request.");
realSubject.request();
System.out.println("After request.");
}
}
public class Client {
public static void main(String[] args) {
Subject realSubject = new RealSubject();
Subject proxy = new StaticProxy(realSubject);
proxy.request();
}
}
JDK动态代理代码示例:
public class JdkDynamicProxy implements InvocationHandler {
private Subject subject;
public JdkDynamicProxy(Subject subject) {
this.subject = subject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before request.");
Object result = method.invoke(subject, args);
System.out.println("After request.");
return result;
}
public static void main(String[] args) {
Subject realSubject = new RealSubject();
Subject proxy = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), new JdkDynamicProxy(realSubject));
proxy.request();
}
}
Cglib动态代理代码示例:
public class CglibDynamicProxy implements MethodInterceptor {
private Object targetObject;
public CglibDynamicProxy(Object targetObject) {
this.targetObject = targetObject;
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("Before request.");
Object result = method.invoke(targetObject, args);
System.out.println("After request.");
return result;
}
public static void main(String[] args) {
RealSubject targetObject = new RealSubject();
CglibDynamicProxy proxy = new CglibDynamicProxy(targetObject);
Subject proxyObject = (Subject) Enhancer.create(targetObject.getClass(), proxy);
proxyObject.request();
}
}