附:2種實現方式詳細對比 Java 動態代理原理圖解( 二 )


CGLib 動態代理實現CGLIB (Code Generation Library) 是一個基于 ASM 的字節碼生成庫,它允許我們在運行時對字節碼進行修改、和動態生成 CGLIB 通過繼承方式實現代理 。

附:2種實現方式詳細對比 Java 動態代理原理圖解

文章插圖
在使用 CGLib 之前,我們要先在項目中引入 CGLib 框架 , 在 pom.xml 中添加如下配置:
<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.3.0</version></dependency>
附:2種實現方式詳細對比 Java 動態代理原理圖解

文章插圖
附:2種實現方式詳細對比 Java 動態代理原理圖解

文章插圖
CGLib 的實現代碼:
package com.mikechen.proxydemo; import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; public class CGLibExample { static class Car {public void running() {System.out.println("The car is running.");}} /*** CGLib 代理類*/static class CGLibProxy implements MethodInterceptor {private Object target; // 代理對象 public Object getInstance(Object target) {this.target = target;Enhancer enhancer = new Enhancer();// 設置父類為實例類enhancer.setSuperclass(this.target.getClass());// 回調方法enhancer.setCallback(this);// 創建代理對象return enhancer.create();} @Overridepublic Object intercept(Object o, Method method,Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("方法調用前業務處理.");Object result = methodProxy.invokeSuper(o, objects); // 執行方法調用return result;}} // 執行 CGLib 的方法調用public static void main(String[] args) {// 創建 CGLib 代理類CGLibProxy proxy = new CGLibProxy();// 初始化代理對象Car car = (Car) proxy.getInstance(new Car());// 執行方法car.running();
附:2種實現方式詳細對比 Java 動態代理原理圖解

文章插圖
附:2種實現方式詳細對比 Java 動態代理原理圖解

文章插圖
以上程序的執行結果是:
方法調用前業務處理 。
The car is running.
附:2種實現方式詳細對比 Java 動態代理原理圖解

文章插圖
附:2種實現方式詳細對比 Java 動態代理原理圖解

文章插圖
可以看出:
CGLib 和 JDK Proxy 的實現代碼比較類似,都是通過實現代理器的接口,再調用某一個方法完成動態代理的 。
唯一不同的是,CGLib 在初始化被代理類時,是通過 Enhancer 對象把代理對象設置為被代理類的子類,來實現動態代理的 。
因此 , 被代理類不能被關鍵字 final 修飾,如果被 final 修飾,再使用 Enhancer 設置父類時會報錯 , 動態代理的構建會失敗 。
JDK 動態代理與 CGLib 的區別1.  JDK 動態代理具體實現原理
  • 通過實現 InvocationHandler 接口,創建自己的調用處理器;
  • 通過為 Proxy 類指定 ClassLoader 對象和一組 interface  , 來創建動態代理;
  • 通過反射機制獲取動態代理類的構造函數,其唯一參數類型就是調用處理器接口類型;
  • 通過構造函數創建動態代理類實例,構造時調用處理器對象作為參數參入 。
2.  CGLib 動態代理
CGLib 是一個強大、高性能的 Code 生產類庫,可以實現運行期動態擴展 java 類,Spring 在運行期間通過 CGlib 繼承要被動態代理的類 , 重寫父類的方法,實現 AOP 面向切面編程 。
3.  兩者對比
  • JDK 動態代理是面向接口的 。
  • CGLib 動態代理是通過字節碼底層繼承要代理類來實現(如果被代理類被 final 關鍵字所修飾 , 會失?。?。
4.  性能對比
  • CGLib 所創建的動態代理對象,在實際運行時候的性能要比 JDK 動態代理高不少,有研究表明,大概要高出10倍;
  • CGLib 在創建對象的時候所花費的時間,比 JDK 動態代理要多很多,有研究表明,大概要高出8倍 。
因此,對于 singleton 的代理對象或者具有實例池的代理,因為無需頻繁的創建代理對象,更適合采用 CGLib 動態代理,反之,則比較適用 JDK 動態代理 。
【附:2種實現方式詳細對比 Java 動態代理原理圖解】以上,是關于 Java 動態代理原理、以及動態代理2 種實現方式的解析 。

推薦閱讀