天天看點

學習動态代理的總結

這兩天好好研究了動态代理,把一些體會寫出來,以備後用

代理分為靜态代理和動态代理

靜态代理需要手動為每個代理類的每個方法添加要實作的功能(如日志)

而動态代理則為需要添加功能的類自動生成代理類,其實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位元組碼

-----------------------------自己的了解,不足之處,懇請指點---------------------------------------------------

繼續閱讀