JDK實作動态代理
思維導圖:點選打開
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsISPrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdsATOfd3bkFGazxCMx8VesATMfhHLlN3XnxCMwEzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5CO2YWNxAzYjBDMmNDNwUjYhJ2MihTO5UzY2EGZmJGNj9CX0AzLclDMxIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLzM3Lc9CX6MHc0RHaiojIsJye.png)
代理模式是指:為其他對象提供一種代理用以控制這個對象的通路。
在某些情況下,一個對象不适合或者不能直接引用另一個對象,而代理對象可以在客戶類和目标類之間起到中介的作用。——————百度百科《代理模式》
生活中的例子:
房産中介
代購
媒婆
在代理中控制用戶端能否調用目标對象的方法。
完成目标對象的調用時,附加一些額外功能,這些額外功能就是增強功能。
比如媒婆要求中介費用
代理模式分為靜态代理和動态代理
靜态代理是指:代理類在程式運作前就已經定義好了.java源檔案,代理類和目标類的關系在程式運作前就已經确立了。在程式運作前代理類就已經編譯成了.class檔案。
1.優點
容易了解
使用比較友善
2.缺點
目标類較多時,會産生大量代理類
當接口改變時,影響的目标類較多
動态代理是指:代理類對象是在運作時,由JVM根據反射機制動态生成的。動态代理不需要定義代理類的.java源檔案。
動态代理其實就是JDK運作期間,動态建立class位元組碼檔案并加載到JVM
不用建立類檔案
當修改了接口中的方法時,不會影響代理類
不用給不同的目标随時建立代理
1.JDK動态代理:
使用java反射包中的類和接口實作動态代理的功能。
反射包:java.lang.reflect
使用的類:
InvocationHandler
Method
Proxy
2.CGLIB動态代理:
cglib時第三方的工具庫,用于建立代理對象。
cglib的原理是繼承,cglib通過繼承目标類,建立其子類,在子類中重寫父類中同名的方法,實作功能的修改。
因為cglib需要繼承目标類,是以要求目标類不能是final的,方法也不能是final的。
cglib對于目标類的要求比較寬松,隻要能繼承就可以。
cglib在很多架構中使用,如mybatis,spring架構。
jdk的動态代理是基于Java的反射機制實作的。使用jdk中的接口和類來實作代理對象的動态建立。
jdk的動态代理要求目标對象必須實作接口。
InvocationHandler接口叫做調用處理器,該接口隻有一個抽象方法:invoke()。
在InvocationHandler接口的實作類中,實作調用目标方法并增強功能的語句就寫在invoke()方法裡。
proxy:代表生成的代理對象
method:代表目标方法
args:代表目标方法的參數
這三個參數都是jdk運作是指派的,無需程式員給出。
InvocationHandler接口的invoke()方法中,第二個參數就是Method類對象,該類中也有一個invoke()方法,可以調用目标方法。這兩個invoke()方法雖然同名,但是沒有關系。
該方法的作用是:調用執行obj對象所屬類的方法,該方法由調用者Method對象确定。
在代碼中,一般寫法為:
其中,method是InvocationHandler接口invoke方法的第二個參數。
通過JDK的java.lang.reflect.Proxy類實作動态代理,會使用其靜态方法newProxyInstance(),根據目标對象、業務接口以及調用處理器,自動生成一個動态代理對象。
loader:目标類的類加載器,通過目标對象的反射可以擷取【目标對象.getClass().getClassLoader()】
interfaces:目标類實作的接口數組,同樣可以通過目标對象的反射擷取【目标對象.getClass().getInterfaces()】
h:調用處理器,也就是InvocationHandler接口實作類對象
建立目标接口,定義目标類要完成的功能
建立目标類來實作目标接口
建立InvocationHandler接口的實作類,在invoke方法中完成代理類的功能
調用目标類的方法
增強功能
使用Proxy類的靜态方法,建立代理對象。并把傳回值也就是代理對象轉為接口類型。
定義目标類要完成的功能
在invoke方法中完成代理類的功能
執行結果: