動態代理是代理模式的實現,在程序運行時,運用反射機制動態創建而成。Java動態代理是Java語言世界的動態代理。
爲了更好地理解動態代理,我們先講述一下代理模式。
代理模式一種軟件設計模式, 是代理類與委託類有同樣的接口。代理類主要負責爲委託類預處理消息、過濾消息、把消息轉發給委託類,以及事後處理消息等。
如下面代理模式比較通用的類圖,Proxy是代理類,RealSubject是目標類,它們實現了同樣的接口。也就是說Proxy類可以用在RealSubject使用的地方。
動態代理相比靜態代理的不同在於:靜態代理是由程序員創建或特定工具自動生成源代碼,再對其編譯,在程序運行前,代理類就已經存在了。在Java程序中,也就是代理類的.class文件就已經存在了。 而動態代理的代理類是在程序運行時,運用反射機制動態創建而成。
Java動態代理的兩種實現:JDK動態代理和CGLib動態代理
-
JDK 動態代理
JDK動態代理是Java 原生的動態代理方法,不需要依賴任何第三方庫。通過java.lang.reflect.Proxy.newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
方法來動態生成代理類。該方法有三個參數:
loader: 加載代理類的ClassLoader
interfaces: 代理類代理的目標類的接口
h:代理類的攔截器,通過定義實現InvocationHandler接口的類來實現自己的攔截器。
生成的代理類,類名如$ProxyXXX。如下面類圖, 代理類$ProxyXXX繼承java.lang.reflect.Proxy,並實現一個或者多個目標類的接口。在java.lang.reflect.Proxy類中有一個InvocationHandler類型的屬性h,表示用戶定義的攔截器。MyInvocationHandler是我們自定義的一個攔截器,其中有一個myTargetObject屬性表示目標對象(這個不是必須的,但如果需要代理對象,我們可以將代理對象放在這),還有一個invoke方法,該方法是覆蓋了接口中的invoke方法,當調用代理類的方法時,會調用攔截器的invoke方法。
-
CGLib 動態代理
CGLib 動態代理是通過使用一個小而快的字節處理框架ASM(Java字節碼操控框架)來轉換字節碼並生成動態代理需要的類。CGLib除了生成我們需要的代理類,還會生成一些輔助類。
生成的代理圖如下面類圖,ObjectClass是我們的目標類,ObjectClass$$EhanceByCGLib$$****是動態生成的代理類,其中有CGLib$CALLBACK_X屬性是攔截器。MyMethodInterceptor是我們自己實現的攔截器,其中有一個targetObject屬性是代理的目標對象(這個不是必須的,但如果需要代理對象,我們可以將代理對象放在這)。而intercept方法是覆蓋的MethodIntercepter的方法, 當調用代理類的方法時,會調用攔截器的intercept 方法。