動態代理與靜態代理的區別
代理模式是一種常見的設計模式,用于在不修改原始類的情況下擴展其功能。代理分為靜態代理和動態代理兩種,它們在實現方式、適用場景和靈活性上有顯著差異。
靜態代理
靜態代理在編譯時就已經確定代理類和被代理類的關系。代理類和被代理類實現相同的接口或繼承相同的父類,代理類在調用被代理類方法前后可以添加額外的邏輯。
- 實現方式:需要手動編寫代理類,顯式調用被代理對象的方法。
- 優點:結構簡單,容易理解和實現。
- 缺點:每個被代理類都需要一個對應的代理類,代碼冗余度高,維護成本較大。
示例代碼:
// 接口
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();}
}
主要區別
- 生成時機:靜態代理在編譯時生成代理類;動態代理在運行時生成代理類。
- 代碼量:靜態代理需要為每個被代理類編寫代理類;動態代理通過通用邏輯處理多個被代理類。
- 靈活性:動態代理更靈活,適合代理多個類或接口;靜態代理適合簡單場景。
- 性能:靜態代理直接調用方法,性能更高;動態代理涉及反射調用,性能略低。
適用場景
- 靜態代理:代理邏輯簡單,被代理類數量較少。
- 動態代理:需要代理多個類或接口,或代理邏輯需要動態變化。
通過比較可以看出,動態代理更適合復雜的業務場景,而靜態代理適合簡單且固定的需求。