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

?

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

文章插圖
動態代理在 Java 中有著廣泛的應用 , 例如:Spring AOP 面向切面編程,Hibernate 數據查詢、以及 RPC Dubbo 遠程調用等,都有非常多的實際應用@mikechen
目錄
  • Java 動態代理原理
  • JDK 原生動態代理
  • CGLib 動態代理實現
  • JDK 動態代理與 CGLib 的區別
Java 動態代理原理按照代理的創建時期,代理類可以分為兩種:
附:2種實現方式詳細對比 Java 動態代理原理圖解

文章插圖
  • 靜態代理:由程序員創建或特定工具自動生成源代碼,再對其編譯,在程序運行前,代理類的 .class 文件就已經存在了 。
  • 動態代理:在程序運行時 , 可以運用反射機制動態創建代理類的 .class 文件 。
動態代理類與靜態代理類最主要的不同點是:代理類的字節碼不是在程序運行前生成的 , 而是在程序運行時再虛擬機中程序自動創建的 。
動態代理的實現方式很多 。例如:JDK 自身提供的動態代理,就利用了上面提到的反射機制 。除了反射,動態代理還可以通過 CGLib 來實現,而 CGLib 是基于 ASM(一個 Java 字節碼操作框架)而非反射實現的 。
簡單來說,動態代理是一種行為方式,而 反射或 ASM 只是它的一種實現手段而已 。
本文我主要詳解 Java 動態代理的 2 種主流現方式:JDK 原生動態代理與 CGLib。
附:2種實現方式詳細對比 Java 動態代理原理圖解

文章插圖
JDK 原生動態代理JDK Proxy 動態代理的實現無需引用第三方類,只需要實現 InvocationHandler 接口,重寫 invoke() 方法即可,整個實現代碼如下所示:、
import java.lang.reflect.InvocationHandler;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.lang.reflect.Proxy; /*** JDK Proxy 相關示例*/public class ProxyExample {static interface Car {void running();} static class Bus implements Car {@Overridepublic void running() {System.out.println("The bus is running.");}} static class Taxi implements Car {@Overridepublic void running() {System.out.println("The taxi is running.");}} /*** JDK Proxy*/static class JDKProxy implements InvocationHandler {private Object target; // 代理對象 // 獲取到代理對象public Object getInstance(Object target) {this.target = target;// 取得代理對象return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(), this);} /*** 執行代理方法* @param proxy 代理對象* @param method 代理方法* @param args 方法的參數* @return* @throws InvocationTargetException* @throws IllegalAccessException*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws InvocationTargetException, IllegalAccessException {System.out.println("動態代理之前的業務處理.");Object result = method.invoke(target, args); // 執行調用方法(此方法執行前后 , 可以進行相關業務處理)return result;}} public static void main(String[] args) {// 執行 JDK ProxyJDKProxy jdkProxy = new JDKProxy();Car carInstance = (Car) jdkProxy.getInstance(new Taxi());carInstance.running();
附:2種實現方式詳細對比 Java 動態代理原理圖解

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

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

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

文章插圖
可以看出,JDK Proxy 實現動態代理的核心是實現 Invocation 接口 , 我們查看 Invocation 的源碼,會發現里面其實只有一個 invoke() 方法,源碼如下:
public interface InvocationHandler {public Object invoke(Object proxy, Method method, Object[] args)throws Throwable;}
附:2種實現方式詳細對比 Java 動態代理原理圖解

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

文章插圖
這是因為在動態代理中有一個重要的角色,也就是代理器,它用于統一管理被代理的對象,顯然 InvocationHandler 就是這個代理器 。而 invoke() 方法 , 則是觸發代理的執行方法,我們通過實現 Invocation 接口來擁有動態代理的能力 。

推薦閱讀