天天看點

JDK實作動态代理

JDK實作動态代理

思維導圖:點選打開

JDK實作動态代理

代理模式是指:為其他對象提供一種代理用以控制這個對象的通路。

在某些情況下,一個對象不适合或者不能直接引用另一個對象,而代理對象可以在客戶類和目标類之間起到中介的作用。——————百度百科《代理模式》

生活中的例子:

房産中介

代購

媒婆

在代理中控制用戶端能否調用目标對象的方法。

完成目标對象的調用時,附加一些額外功能,這些額外功能就是增強功能。

比如媒婆要求中介費用

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

靜态代理是指:代理類在程式運作前就已經定義好了.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方法中完成代理類的功能

執行結果: