這兩天好好研究了動态代理,把一些體會寫出來,以備後用
代理分為靜态代理和動态代理
靜态代理需要手動為每個代理類的每個方法添加要實作的功能(如日志)
而動态代理則為需要添加功能的類自動生成代理類,其實jdk proxy已經為我們提供了方法
靜态代理就是面向對象中的代理模式,使用面向對象的方式實作代理對象,這個代理對象的類是自己手工編寫的。
動态代理是程式設計語言根據代理規則自動生成代理類,并産生代理對象。常用的動态代理有 JDK Proxy 和 cglib。
JDK Proxy 是在運作時産生代理類的位元組碼,再由類加載器加載這些位元組碼然後建立代理對象。
Cglib 是使用一種叫做 ASM 的位元組碼工具,由程式的方式産生位元組碼。
迷惑的地方時invoke方法是何時被執行的
我們在InvocationHandler實作類中寫一個newInstance(),用來産生代理類,傳回一個object類型的 new Proxy.newProxyInstance(loader, interfaces, h)的代理類
裡面有三個參數,第一個是用來将目标對象(即真實類)加載到JVM上,第二個是實作目标對象接口的所有方法,有意思的是第三個方法,當我們調用目标對象的方法時,就會轉到第三個參數,它指的是代理類對象,講調用第三個方法時,它會自動調用invoke方法
在invoke(Object proxy, Method method, Object[] args)方法中,
Object proxy -----代理類對象
Method method -----被代理對象的方法(這裡不是接口的抽象方法了,是具體的實作類中的方法)
Object[] args -----該方法的參數數組
在方法裡面可以加入需要添加的如日志,安全性檢查功能
方法裡面需要實作的就一句,method.invoke(target,args);
即目标對象,參數,它的作用就是執行目标對象裡面的方法
參考了下面的講解
1. Proxy即動态代理類;
2. Static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h):傳回代理類的一個執行個體,傳回後的代理類可以當作被代理類使用;
它有三個參數:
ClassLoader loader ----指定被代理對象的類加載器
Class[] Interfaces ----指定被代理對象是以事項的接口
InvocationHandler h ----指定需要調用的InvocationHandler對象
3. 實作InVocationHandler接口的LogHandler_old對象
這個對象的invoke()方法就是Proxy這個動态代理類所代理的接口類的抽象方法的真實實作;
它有三個參數:
Object proxy -----代理類對象
Method method -----被代理對象的方法(這裡不是接口的抽象方法了,是具體的實作類中的方法)
Object[] args -----該方法的參數數組
JDK中具體的動态代理類是怎麼産生的呢?
1.産生代理類$Proxy0類
執行了Proxy.newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)
将産生$Proxy0類,它繼承Proxy對象,并根據第二個參數,實作了被代理類的所有接口,自然就可以生成接口要實作的所有方法了(這時候會重寫hashcode,toString和equals三個方法),但是還沒有具體的實作體;
2. 将代理類$Proxy0類加載到JVM中
這時候是根據Proxy.newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)它的第一個參數----就是被代理類的類加載器,把目前的代理類加載到JVM中
3. 建立代理類$Proxy0類的對象
調用的$Proxy0類的$Proxy0(InvocationHandler)構造函數,生成$Proxy0類的對象
參數就是Proxy.newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)它的第三個參數
這個參數就是我們自己實作的InvocationHandler對象,我們知道InvocationHandler對象中組合加入了代理類代理的接口類的實作類;是以,$Proxy0對象調用所有要實作的接口的方法,都會調用InvocationHandler對象的invoke()方法實作;
4. 生成代理類的class byte
動态代理生成的都是二進制class位元組碼
-----------------------------自己的了解,不足之處,懇請指點---------------------------------------------------