代理的概念
為某個對象提供一個代理,以控制對這個對象的訪問。 代理類和委托類有共同的父類或父接口,這樣在任何使用委托類對象的地方都可以用代理對象替代。代理類負(fù)責(zé)請求的預(yù)處理、過濾、將請求分派給委托類處理、以及委托類執(zhí)行完請求后的后續(xù)處理。
動態(tài)代理
動態(tài)代理類的源碼是在程序運行期間由JVM根據(jù)反射等機制動態(tài)的生成,所以不存在代理類的字節(jié)碼文件。代理類和委托類的關(guān)系是在程序運行時確定。
在java的動態(tài)代理API中,有兩個重要的類和接口,一個是Proxy(Class)、另一個則是 InvocationHandler(Interface),這一個類和接口是實現(xiàn)我們動態(tài)代理所必須用到的
動態(tài)代理設(shè)計模式
![GWY96GFG]QC)IP45~}6__2.png
1、被代理類+增強=生成新的類(java)
2、編譯新的類(class)
3、加載新的類
4、創(chuàng)建代理對象$Proxy12 (12是隨機數(shù))
Proxy(Class)(一般我們用最后一種方法)
Proxy是 Java 動態(tài)代理機制的主類,它提供了一組靜態(tài)方法來為一組接口動態(tài)地生成代理類及其對象。
Proxy 的靜態(tài)方法
static InvocationHandler getInvocationHandler(Object proxy)
該方法用于獲取指定代理對象所關(guān)聯(lián)的調(diào)用處理器
static Class getProxyClass(ClassLoader loader, Class[] interfaces)
該方法用于獲取關(guān)聯(lián)于指定類裝載器和一組接口的動態(tài)代理類的類對象
static boolean isProxyClass(Class cl)
該方法用于判斷指定類對象是否是一個動態(tài)代理類
static Object newProxyInstance(ClassLoader loader, Class[] interfaces,InvocationHandler h)
loader 指定代理類的ClassLoader加載器
interfaces 指定代理類要實現(xiàn)的接口
h: 表示的是當(dāng)我這個動態(tài)代理對象在調(diào)用方法的時候,會關(guān)聯(lián)到哪一個InvocationHandler對象上
該方法用于為指定類裝載器、一組接口及調(diào)用處理器生成動態(tài)代理類實例
InvocationHandler(Interface)
InvocationHandler是負(fù)責(zé)連接代理類和委托類的中間類必須實現(xiàn)的接口,它自定義了一個 invoke 方法,用于集中處理在動態(tài)代理類對象上的方法調(diào)用,通常在該方法中實現(xiàn)對委托類的代理訪問。
InvocationHandler 的核心方法
Object invoke(Object proxy, Method method, Object[] args)
proxy 該參數(shù)為代理類的實例
method 被調(diào)用的方法對象
args 調(diào)用method對象的方法參數(shù)
該方法也是InvocationHandler接口所定義的唯一的一個方法,該方法負(fù)責(zé)集中處理動態(tài)代理類上的所有方法的調(diào)用。調(diào)用處理器根據(jù)這三個參數(shù)進行預(yù)處理或分派到委托類實例上執(zhí)行。
動態(tài)代理的優(yōu)點和缺點
優(yōu)點
接口中聲明的所有方法都被轉(zhuǎn)移到調(diào)用處理器一個集中的方法中處理(InvocationHandler.invoke)。這樣,在接口方法數(shù)量比較多的時候,我們可以進行靈活處理
缺點
它始終無法擺脫僅支持 interface 代理的桎梏,它們已經(jīng)注定有一個共同的父類叫 Proxy。Java 的繼承機制注定了這些動態(tài)代理類們無法實現(xiàn)對 class 的動態(tài)代理,原因是多繼承在 Java 中本質(zhì)上就行不通。
舉例
public interface IDrink {
public default void drink(){
System.out.println("喝咖啡");
}
}
public class Coffee implements IDrink{
public void drink(){
System.out.println("喝咖啡");
}
}
public class MilkHandler implements InvocationHandler{
Object obj=null;
public MilkHandler(Object obj){
this.obj=obj;
}
//proxy:被代理對象 method:需要被增強的方法 args:方法的參數(shù)
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("加牛奶");
method.invoke(obj, args);//通過反射調(diào)用加牛奶的方法
return null;
}
}
public class Test {
public static void main(String[] args) {
Coffee c=new Coffee();//實現(xiàn)IDrink接口
MilkHandler h=new MilkHandler(c);
IDrink d=(IDrink)Proxy.newProxyInstance(c.getClass().getClassLoader(), c.getClass().getInterfaces(), h);//實現(xiàn)了IDrink接口
d.drink();
}
}