動態代理是指代理類對象在程序運行時由JVM根據反射機制動態生成的。動態代理不需要定義代理類的.java源文件。
動態代理其實就是jdk運行期間,動態創建class字節碼并加載到JVM。
動態代理的實現方式常用的有兩種:使用JDK代理代理,與通過CGLIB動態代理。
jdk動態代理是基于Java的反射機制實現的。使用jdk中接口和類實現代理對象的動態創建。
Jdk的動態要求目標對象必須實現接口,這是java設計上的要求。
從jdk1.3以來,java語言通過java.lang.reflect包提供三個類支持代理模式Proxy, Method和InovcationHandler。
⒈ InvocationHandler接口
InvocationHandler接口叫做調用處理器,負責完調用目標方法,并增強功能。
通過代理對象執行目標接口中的方法,會把方法的調用分派給調用處理器(InvocationHandler)的實現類,執行實現類中的invoke()方法,我們需要把功能代理寫在invoke()方法中 。
接口中只有一個方法:
在invoke方法中可以截取對目標方法的調用。在這里進行功能增強。Java的動態代理是建立在反射機制之上的。
實現了InvocationHandler接口的類用于加強目標類的主業務邏輯。這個接口中有一個方法invoke(),具體加強的代碼邏輯就是定義在該方法中的。通過代理對象執行接口中的方法時,會自動調用invoke()方法。
invoke()方法的介紹如下:
public Object invoke ( Object proxy, Method method, Object[] args)
proxy:代表生成的代理對象
method:代表目標方法
args:代表目標方法的參數
第一個參數proxy是jdk在運行時賦值的,在方法中直接使用,第二個參數后面介紹,第三個參數是方法執行的參數, 這三個參數都是jdk運行時賦值的,無需程序員給出。
⒉Method 類
invoke()方法的第二個參數為Method類對象,該類有一個方法也叫invoke(),可以調用目標方法。這兩個invoke()方法,雖然同名,但無關。
public Object invoke ( Object?obj, Object...?args)
obj:表示目標對象
args:表示目標方法參數,就是其上一層invoke方法的第三個參數
該方法的作用是:調用執行obj對象所屬類的方法,這個方法由其調用者Method對象確定。
在代碼中,一般的寫法為method.invoke(target, args);其中,method為上一層invoke方法的第二個參數。這樣,即可調用了目標類的目標方法。
⒊Proxy類
通過JDK的java.lang.reflect.Proxy類實現動態代理,會使用其靜態方法newProxyInstance(),依據目標對象、業務接口及調用處理器三者,自動生成一個動態代理對象。
public static newProxyInstance ( ClassLoader loader, Class<?>[] interfaces,
InvocationHandler handler)
loader:目標類的類加載器,通過目標對象的反射可獲取
interfaces:目標類實現的接口數組,通過目標對象的反射可獲取
handler:調用處理器。
jdk動態代理實現
jdk動態代理是代理模式的一種實現方式,其只能代理接口。
實現步驟:
① 新建一個接口,作為目標接口
② 為接口創建一個實現類,是目標類
③ 創建類實現java.lang.reflect.InvocationHandler接口,調用目標方法并增加其他功能代碼
④ 創建動態代理對象,使用Proxy.newProxyInstance()方法,并把返回值強制轉為接口類型。
idea創建java project
工程名稱:ch02-dynamicproxy
⒈定義目標接口
⒉定義目標接口實現類
⒊定義調用處理程序
調用處理程序是實現了InvocationHandler的類,在invoke方法中增加業務功能。還需要創建有參構造,參數是目標對象。為的是完成對目標對象的方法調用。
⒋創建動態代理對象
執行流程:
類圖:
CGLIB(Code Generation Library)是一個開源項目。是一個強大的,高性能,高質量的Code生成類庫,它可以在運行期擴展Java類與實現Java接口。它廣泛的被許多AOP的框架使用,例如Spring AOP。
使用JDK的Proxy實現代理,要求目標類與代理類實現相同的接口。若目標類不存在接口,則無法使用該方式實現。
但對于無接口的類,要為其創建動態代理,就要使用CGLIB來實現。CGLIB代理的生成原理是生成目標類的子類,而子類是增強過的,這個子類對象就是代理對象。所以,使用CGLIB生成動態代理,要求目標類必須能夠被繼承,即不能是final的類。
cglib經常被應用在框架中,例如Spring ,Hibernate等。Cglib的代理效率高于Jdk。對于cglib一般的開發中并不使用。做了一個了解就可以。