晓知识: 动态代理与静态代理的区别
动态代理与静态代理的区别
代理模式是一种常见的设计模式,用于在不修改原始类的情况下扩展其功能。代理分为静态代理和动态代理两种,它们在实现方式、适用场景和灵活性上有显著差异。
静态代理
静态代理在编译时就已经确定代理类和被代理类的关系。代理类和被代理类实现相同的接口或继承相同的父类,代理类在调用被代理类方法前后可以添加额外的逻辑。
- 实现方式:需要手动编写代理类,显式调用被代理对象的方法。
- 优点:结构简单,容易理解和实现。
- 缺点:每个被代理类都需要一个对应的代理类,代码冗余度高,维护成本较大。
示例代码:
// 接口
public interface Subject {void request();
}// 被代理类
public class RealSubject implements Subject {@Overridepublic void request() {System.out.println("RealSubject request");}
}// 代理类
public class StaticProxy implements Subject {private RealSubject realSubject;public StaticProxy(RealSubject realSubject) {this.realSubject = realSubject;}@Overridepublic void request() {System.out.println("Before request");realSubject.request();System.out.println("After request");}
}
动态代理
动态代理在运行时动态生成代理类,无需手动编写代理类代码。Java中可以通过java.lang.reflect.Proxy
或第三方库(如CGLIB)实现动态代理。
- 实现方式:通过反射机制动态生成代理类,代理逻辑由
InvocationHandler
实现。 - 优点:减少代码冗余,一个代理类可以代理多个接口或类,灵活性高。
- 缺点:性能略低于静态代理,实现复杂度较高。
示例代码(基于JDK动态代理):
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;public class DynamicProxyExample {public static void main(String[] args) {RealSubject realSubject = new RealSubject();Subject proxyInstance = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(),realSubject.getClass().getInterfaces(),new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("Before request");Object result = method.invoke(realSubject, args);System.out.println("After request");return result;}});proxyInstance.request();}
}
主要区别
- 生成时机:静态代理在编译时生成代理类;动态代理在运行时生成代理类。
- 代码量:静态代理需要为每个被代理类编写代理类;动态代理通过通用逻辑处理多个被代理类。
- 灵活性:动态代理更灵活,适合代理多个类或接口;静态代理适合简单场景。
- 性能:静态代理直接调用方法,性能更高;动态代理涉及反射调用,性能略低。
适用场景
- 静态代理:代理逻辑简单,被代理类数量较少。
- 动态代理:需要代理多个类或接口,或代理逻辑需要动态变化。
通过比较可以看出,动态代理更适合复杂的业务场景,而静态代理适合简单且固定的需求。