靜態代理
靜態代理是由程序員創建或工具生成代理類的源碼,再編譯代理類。
所謂靜態也就是在程序運行前就已經存在代理類的字節碼文件,代理類和委託類的關係在運行前就確定了。
(1)基於接口實現方式
(2)接口繼承方式實現
public class OrderServiceProxy extends OrderServiceImpl {
public void order() {
System.out.println("前置通知..");
super.order();
System.out.println("後置通知..");
}
}
public class ClientTest {
public static void main(String[] args) {
OrderService orderService = new OrderServiceProxy();
orderService.order();
}
}
動態代理
動態代理是在實現階段不用關心代理類,而在運行階段才指定哪一個對象。
(1)JDK動態代理
JDK動態代理的一般步驟如下:
1.創建被代理的接口和類;
2.實現InvocationHandler接口,對目標接口中聲明的所有方法進行統一處理;
3.調用Proxy的靜態方法,創建代理類並生成相應的代理對象;
動態代理類的源碼是在程序運行期間由JVM根據反射等機制動態的生成 。
動態代理原理分析:
1、創建代理類$Proxy0源代碼文件實現被代理的接口。
2、使用JavaCompiler技術編譯該$Proxy0文件獲取到$Proxy0.class
3、使用ClassLoader將該$Proxy0.class加入到當前JVM內存中
注意:繼承了Proxy類,實現了代理的接口,由於java不能多繼承,這裏已經繼承了Proxy類了,不能再繼承其他的類,所以JDK的動態代理不支持對實現類的代理,只支持接口的代理。
(2)CGLIB動態代理
Cglib是一個強大的,高性能,高質量的代碼生成類庫。它可以在運行期擴展JAVA類與實現JAVA接口。其底層實現是通過ASM字節碼處理框架來轉換字節碼並生成新的類。大部分功能實際上是ASM所提供的,Cglib只是封裝了ASM,簡化了ASM操作,實現了運行期生成新的class。
CGLIB原理
運行時動態的生成一個被代理類的子類(通過ASM字節碼處理框架實現),子類重寫了被代理類中所有非final的方法。在子類中採用方法攔截的技術攔截所有父類方法的調用,順勢植入橫切邏輯。
Cglib優缺點
優點:JDK動態代理要求被代理的類必須實現接口,當需要代理的類沒有實現接口時Cglib代理是一個很好的選擇。另一個優點是Cglib動態代理比使用java反射的JDK動態代理要快
缺點:對於被代理類中的final方法,無法進行代理,因爲子類中無法重寫final函數
CGLIB代理實現
實現MethodInterceptor接口的intercept方法後,所有生成的代理方法都調用這個方法。
intercept方法的具體參數有
obj 目標類的實例
1. method 目標方法實例(通過反射獲取的目標方法實例)
2. args 目標方法的參數
3. proxy 代理類的實例
該方法的返回值就是目標方法的返回值。