前言
今天Carson來(lái)全面總結(jié)最常用的設(shè)計(jì)模式 - 代理模式中的動(dòng)態(tài)代理模式
其他設(shè)計(jì)模式介紹
這是一份全面 & 詳細(xì)的設(shè)計(jì)模式學(xué)習(xí)指南
Carson帶你學(xué)設(shè)計(jì)模式:?jiǎn)卫J剑⊿ingleton)
Carson帶你學(xué)設(shè)計(jì)模式:簡(jiǎn)單工廠模式(SimpleFactoryPattern)
Carson帶你學(xué)設(shè)計(jì)模式:工廠方法模式(Factory Method)
Carson帶你學(xué)設(shè)計(jì)模式:抽象工廠模式(Abstract Factory)
Carson帶你學(xué)設(shè)計(jì)模式:策略模式(Strategy Pattern)
Carson帶你學(xué)設(shè)計(jì)模式:適配器模式(Adapter Pattern)
Carson帶你學(xué)設(shè)計(jì)模式:靜態(tài)代理模式(Proxy Pattern)
Carson帶你學(xué)設(shè)計(jì)模式:動(dòng)態(tài)代理模式(Proxy Pattern)
Carson帶你學(xué)設(shè)計(jì)模式:模板方法模式(Template Method)
Carson帶你學(xué)設(shè)計(jì)模式:建造者模式(Builder Pattern)
Carson帶你學(xué)設(shè)計(jì)模式:外觀模式(Facade Pattern)
Carson帶你學(xué)設(shè)計(jì)模式:觀察者模式(Observer)
目錄
1. 為什么要使用動(dòng)態(tài)代理
1.1 背景
代理模式中的靜態(tài)代理模式存在一些特點(diǎn):
- 1個(gè)靜態(tài)代理 只服務(wù)1種類型的目標(biāo)對(duì)象
- 若要服務(wù)多類型的目標(biāo)對(duì)象篡悟,則需要為每種目標(biāo)對(duì)象都實(shí)現(xiàn)一個(gè)靜態(tài)代理對(duì)象
關(guān)于靜態(tài)代理模式可以看文章:Carson帶你學(xué)設(shè)計(jì)模式:靜態(tài)代理模式(Proxy Pattern)
1.2 沖突
在目標(biāo)對(duì)象較多的情況下焙矛,若采用靜態(tài)代理,則會(huì)出現(xiàn) 靜態(tài)代理對(duì)象量多羡宙、代碼量大凌盯,從而導(dǎo)致代碼復(fù)雜的問題
1.3 解決方案
采用 動(dòng)態(tài)代理模式孕豹。
2. 動(dòng)態(tài)代理模式介紹
2.1 實(shí)現(xiàn)原理
- 設(shè)計(jì)動(dòng)態(tài)代理類(
DynamicProxy
)時(shí),不需要顯式實(shí)現(xiàn)與目標(biāo)對(duì)象類(RealSubject
)相同的接口十气,而是將這種實(shí)現(xiàn)推遲到程序運(yùn)行時(shí)由JVM
來(lái)實(shí)現(xiàn)
- 即:在使用時(shí)再創(chuàng)建動(dòng)態(tài)代理類 & 實(shí)例
- 靜態(tài)代理則是在代理類實(shí)現(xiàn)時(shí)就指定與目標(biāo)對(duì)象類(
RealSubject
)相同的接口
- 通過
Java
反射機(jī)制的method.invoke()
励背,通過調(diào)用動(dòng)態(tài)代理類對(duì)象方法,從而自動(dòng)調(diào)用目標(biāo)對(duì)象的方法
2.2 優(yōu)點(diǎn)
- 只需要1個(gè)動(dòng)態(tài)代理類就可以解決創(chuàng)建多個(gè)靜態(tài)代理的問題砸西,避免重復(fù)叶眉、多余代碼
- 更強(qiáng)的靈活性
- 設(shè)計(jì)動(dòng)態(tài)代理類(
DynamicProxy
)時(shí),不需要顯式實(shí)現(xiàn)與目標(biāo)對(duì)象類(RealSubject
)相同的接口芹枷,而是將這種實(shí)現(xiàn)推遲到程序運(yùn)行時(shí)由JVM
來(lái)實(shí)現(xiàn)- 在使用時(shí)(調(diào)用目標(biāo)對(duì)象方法時(shí))才會(huì)動(dòng)態(tài)創(chuàng)建動(dòng)態(tài)代理類 & 實(shí)例衅疙,不需要事先實(shí)例化
2.3 缺點(diǎn)
- 效率低
相比靜態(tài)代理中 直接調(diào)用目標(biāo)對(duì)象方法,動(dòng)態(tài)代理則需要先通過Java
反射機(jī)制 從而 間接調(diào)用目標(biāo)對(duì)象方法 - 應(yīng)用場(chǎng)景局限
因?yàn)?Java 的單繼承特性(每個(gè)代理類都繼承了 Proxy 類)鸳慈,即只能針對(duì)接口 創(chuàng)建 代理類饱溢,不能針對(duì)類 創(chuàng)建代理類
即只能動(dòng)態(tài)代理 實(shí)現(xiàn)了接口的類
2.4 應(yīng)用場(chǎng)景
- 基于靜態(tài)代理應(yīng)用場(chǎng)景下,需要代理對(duì)象數(shù)量較多的情況下使用動(dòng)態(tài)代理
-
AOP
領(lǐng)域
- 定義:即
Aspect Oriented Programming
= 面向切面編程走芋,是OOP
的延續(xù)绩郎、函數(shù)式編程的一種衍生范型- 作用:通過預(yù)編譯方式和運(yùn)行期動(dòng)態(tài)代理實(shí)現(xiàn)程序功能的統(tǒng)一維護(hù)。
- 優(yōu)點(diǎn):降低業(yè)務(wù)邏輯各部分之間的耦合度 翁逞、 提高程序的可重用性 & 提高了開發(fā)的效率
- 具體應(yīng)用場(chǎng)景:日志記錄肋杖、性能統(tǒng)計(jì)、安全控制挖函、異常處理等
2.5 與靜態(tài)代理模式的區(qū)別
3. 具體應(yīng)用
接下來(lái)状植,我將用1個(gè)具體實(shí)例來(lái)對(duì) 動(dòng)態(tài)代理模式 進(jìn)行更深一步的介紹
3.1 實(shí)例概況
- 背景:小成 希望買一臺(tái)最新的頂配
Mac
電腦;小何希望買一臺(tái)iPhone
- 沖突:國(guó)內(nèi)還沒上,只有美國(guó)才有
- 解決方案:尋找一個(gè)代購(gòu)一起進(jìn)行購(gòu)買
- 即1個(gè)代購(gòu)(動(dòng)態(tài)代理對(duì)象)同時(shí) 代替 小成 & 小何(目標(biāo)對(duì)象) 去買Mac(間接訪問的操作)
- 該代購(gòu)是代購(gòu)任何商品 = 什么人有什么需求就會(huì)去代購(gòu)任何東西(動(dòng)態(tài)代理)
3.2 使用步驟
- 聲明 調(diào)用處理器類
- 聲明目標(biāo)對(duì)象類的抽象接口
- 聲明目標(biāo)對(duì)象類
- 通過動(dòng)態(tài)代理對(duì)象津畸,調(diào)用目標(biāo)對(duì)象的方法
3.3 步驟詳解
步驟1: 聲明 調(diào)用處理器類
DynamicProxy.java
<-- 作用 -->
// 1. 生成 動(dòng)態(tài)代理對(duì)象
// 2. 指定 代理對(duì)象運(yùn)行目標(biāo)對(duì)象方法時(shí)需要完成的 具體任務(wù)
// 注:需實(shí)現(xiàn)InvocationHandler接口 = 調(diào)用處理器 接口
// 所以稱為 調(diào)用處理器類
public class DynamicProxy implements InvocationHandler {
// 聲明代理對(duì)象
// 作用:綁定關(guān)系振定,即關(guān)聯(lián)到哪個(gè)接口(與具體的實(shí)現(xiàn)類綁定)的哪些方法將被調(diào)用時(shí),執(zhí)行invoke()
private Object ProxyObject;
public Object newProxyInstance(Object ProxyObject){
this.ProxyObject =ProxyObject;
return Proxy.newProxyInstance(ProxyObject.getClass().getClassLoader(),
ProxyObject.getClass().getInterfaces(),this);
// Proxy類 = 動(dòng)態(tài)代理類的主類
// Proxy.newProxyInstance()作用:根據(jù)指定的類裝載器肉拓、一組接口 & 調(diào)用處理器 生成動(dòng)態(tài)代理類實(shí)例后频,并最終返回
// 參數(shù)說(shuō)明:
// 參數(shù)1:指定產(chǎn)生代理對(duì)象的類加載器,需要將其指定為和目標(biāo)對(duì)象同一個(gè)類加載器
// 參數(shù)2:指定目標(biāo)對(duì)象的實(shí)現(xiàn)接口
// 即要給目標(biāo)對(duì)象提供一組什么接口帝簇。若提供了一組接口給它徘郭,那么該代理對(duì)象就默認(rèn)實(shí)現(xiàn)了該接口,這樣就能調(diào)用這組接口中的方法
// 參數(shù)3:指定InvocationHandler對(duì)象丧肴。即動(dòng)態(tài)代理對(duì)象在調(diào)用方法時(shí)残揉,會(huì)關(guān)聯(lián)到哪個(gè)InvocationHandler對(duì)象
}
// 復(fù)寫InvocationHandler接口的invoke()
// 動(dòng)態(tài)代理對(duì)象調(diào)用目標(biāo)對(duì)象的任何方法前,都會(huì)調(diào)用調(diào)用處理器類的invoke()
@Override
public Object invoke(Object proxy, Method method, Object[] args)
// 參數(shù)說(shuō)明:
// 參數(shù)1:動(dòng)態(tài)代理對(duì)象(即哪個(gè)動(dòng)態(tài)代理對(duì)象調(diào)用了method()
// 參數(shù)2:目標(biāo)對(duì)象被調(diào)用的方法
// 參數(shù)3:指定被調(diào)用方法的參數(shù)
throws Throwable {
System.out.println("代購(gòu)出門了");
Object result = null;
// 通過Java反射機(jī)制調(diào)用目標(biāo)對(duì)象方法
result = method.invoke(ProxyObject, args);
return result;
}
}
步驟2: 聲明目標(biāo)對(duì)象的抽象接口
Subject.java
public interface Subject {
// 定義目標(biāo)對(duì)象的接口方法
// 代購(gòu)物品
public void buybuybuy();
}
步驟3: 聲明目標(biāo)對(duì)象類
Buyer1.java
// 小成芋浮,真正的想買Mac的對(duì)象 = 目標(biāo)對(duì)象 = 被代理的對(duì)象
// 實(shí)現(xiàn)抽象目標(biāo)對(duì)象的接口
public class Buyer1 implements Subject {
@Override
public void buybuybuy() {
System.out.println("小成要買Mac");
}
}
Buyer2.java
// 小何抱环,真正的想買iPhone的對(duì)象 = 目標(biāo)對(duì)象 = 被代理的對(duì)象
// 實(shí)現(xiàn)抽象目標(biāo)對(duì)象的接口
public class Buyer2 implements Subject {
@Override
public void buybuybuy() {
System.out.println("小何要買iPhone");
}
}
步驟4: 通過動(dòng)態(tài)代理對(duì)象,調(diào)用目標(biāo)對(duì)象的方法
MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 1. 創(chuàng)建調(diào)用處理器類對(duì)象
DynamicProxy DynamicProxy = new DynamicProxy();
// 2. 創(chuàng)建目標(biāo)對(duì)象對(duì)象
Buyer1 mBuyer1 = new Buyer1();
// 3. 創(chuàng)建動(dòng)態(tài)代理類 & 對(duì)象:通過調(diào)用處理器類對(duì)象newProxyInstance()
// 傳入上述目標(biāo)對(duì)象對(duì)象
Subject Buyer1_DynamicProxy = (Subject) DynamicProxy.newProxyInstance(mBuyer1);
// 4. 通過調(diào)用動(dòng)態(tài)代理對(duì)象方法從而調(diào)用目標(biāo)對(duì)象方法
// 實(shí)際上是調(diào)用了invoke()纸巷,再通過invoke()里的反射機(jī)制調(diào)用目標(biāo)對(duì)象的方法
Buyer1_DynamicProxy.buybuybuy();
// 以上代購(gòu)為小成代購(gòu)Mac
// 以下是代購(gòu)為小何代購(gòu)iPhone
Buyer2 mBuyer2 = new Buyer2();
Subject Buyer2_DynamicProxy = (Subject) DynamicProxy.newProxyInstance(mBuyer2);
Buyer2_DynamicProxy.buybuybuy();
}
}
3.4 測(cè)試結(jié)果
3.5 Demo地址
Carson_Ho的Github地址:動(dòng)態(tài)代理DynamicProxy
4. 源碼分析
-
在經(jīng)過上面的實(shí)例后镇草,你是否會(huì)對(duì)以下問題好奇:
- 動(dòng)態(tài)代理類 及其對(duì)象實(shí)例是如何生成的?
- 如何通過調(diào)用動(dòng)態(tài)代理對(duì)象方法瘤旨,從而調(diào)用目標(biāo)對(duì)象方法梯啤?
下面,我們順著 步驟4:目標(biāo)對(duì)象 通過 動(dòng)態(tài)代理對(duì)象調(diào)用方法的使用 來(lái)進(jìn)行動(dòng)態(tài)代理模式的源碼分析
// 步驟4:通過動(dòng)態(tài)代理對(duì)象存哲,調(diào)用目標(biāo)對(duì)象的方法
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 1. 創(chuàng)建 調(diào)用處理器類 對(duì)象
DynamicProxy DynamicProxy = new DynamicProxy();
// 2. 創(chuàng)建 目標(biāo)類 對(duì)象
Buyer1 mBuyer1 = new Buyer1();
// 3. 創(chuàng)建動(dòng)態(tài)代理類 & 對(duì)象:通過調(diào)用處理器類對(duì)象newProxyInstance()
// 傳入上述目標(biāo)類對(duì)象
Subject Buyer1_DynamicProxy = (Subject) DynamicProxy.newProxyInstance(mBuyer1);
// ->>關(guān)注1
// 4. 通過調(diào)用動(dòng)態(tài)代理對(duì)象方法從而調(diào)用目標(biāo)對(duì)象方法
// ->>關(guān)注2
Buyer1_DynamicProxy.buybuybuy();
// 以上代購(gòu)為小成代購(gòu)Mac
// 以下是代購(gòu)為小何代購(gòu)iPhone
Buyer2 mBuyer2 = new Buyer2();
Subject Buyer2_DynamicProxy = (Subject) DynamicProxy.newProxyInstance(mBuyer2);
Buyer2_DynamicProxy.buybuybuy();
}
}
此處有兩個(gè)重要的源碼分析點(diǎn):
- 關(guān)注1:創(chuàng)建動(dòng)態(tài)代理類 & 對(duì)象:通過調(diào)用處理器類對(duì)象
newProxyInstance()
解決的問題是:動(dòng)態(tài)代理類 及其對(duì)象實(shí)例是如何生成的因宇?
- 關(guān)注2:通過調(diào)用動(dòng)態(tài)代理對(duì)象方法從而調(diào)用目標(biāo)對(duì)象方法
解決的問題是:如何通過調(diào)用動(dòng)態(tài)代理對(duì)象方法,從而調(diào)用目標(biāo)對(duì)象方法祟偷?
下面察滑,我們將主要分析這兩處源碼。
4.1 (關(guān)注1)創(chuàng)建動(dòng)態(tài)代理類 & 對(duì)象:通過調(diào)用處理器類對(duì)象newProxyInstance()
// 使用代碼
Subject Buyer1_DynamicProxy = (Subject) DynamicProxy.newProxyInstance(mBuyer1);
- 即修肠,動(dòng)態(tài)代理類 及其對(duì)象實(shí)例是如何生成的贺辰?
- 下面,我們直接進(jìn)入
DynamicProxy.newProxyInstance()
<-- 關(guān)注1:調(diào)用處理器 類的newProxyInstance() -->
// 即步驟1中實(shí)現(xiàn)的類:DynamicProxy
// 作用:
// 1. 生成 動(dòng)態(tài)代理對(duì)象
// 2. 指定 代理對(duì)象運(yùn)行目標(biāo)對(duì)象方法時(shí)需要完成的 具體任務(wù)
// 注:需實(shí)現(xiàn)InvocationHandler接口 = 調(diào)用處理器 接口
public class DynamicProxy implements InvocationHandler {
// 聲明代理對(duì)象
private Object ProxyObject;
public Object newProxyInstance(Object ProxyObject){
this.ProxyObject =ProxyObject;
return Proxy.newProxyInstance(ProxyObject.getClass().getClassLoader(),
ProxyObject.getClass().getInterfaces(),this);
// Proxy.newProxyInstance()作用:根據(jù)指定的類裝載器嵌施、一組接口 & 調(diào)用處理器 生成動(dòng)態(tài)代理類實(shí)例饲化,并最終返回
// ->>關(guān)注2
}
// 以下暫時(shí)忽略,下文會(huì)詳細(xì)介紹
// 復(fù)寫InvocationHandler接口的invoke()
// 動(dòng)態(tài)代理對(duì)象調(diào)用目標(biāo)對(duì)象的任何方法前艰管,都會(huì)調(diào)用調(diào)用處理器類的invoke()
@Override
public Object invoke(Object proxy, Method method, Object[] args)
// 參數(shù)說(shuō)明:
// 參數(shù)1:動(dòng)態(tài)代理對(duì)象(即哪個(gè)動(dòng)態(tài)代理對(duì)象調(diào)用了method()
// 參數(shù)2:目標(biāo)對(duì)象被調(diào)用的方法
// 參數(shù)3:指定被調(diào)用方法的參數(shù)
throws Throwable {
System.out.println("代購(gòu)出門了");
Object result = null;
// 通過Java反射機(jī)制調(diào)用目標(biāo)對(duì)象方法
result = method.invoke(ProxyObject, args);
return result;
}
// 至此滓侍,關(guān)注1分析完畢,跳出
}
<-- 關(guān)注2:newProxyInstance()源碼解析-->
// 作用:根據(jù)指定的類裝載器牲芋、一組接口 & 調(diào)用處理器 生成動(dòng)態(tài)代理類及其對(duì)象實(shí)例,并最終返回
public static Object newProxyInstance(ClassLoader loader, Class<?>[]interfaces,InvocationHandler h) throws IllegalArgumentException {
// 參數(shù)說(shuō)明:
// 參數(shù)1:指定產(chǎn)生代理對(duì)象的類加載器,需要將其指定為和目標(biāo)對(duì)象同一個(gè)類加載器
// 參數(shù)2:指定目標(biāo)對(duì)象的實(shí)現(xiàn)接口
// 即要給目標(biāo)對(duì)象提供一組什么接口缸浦。若提供了一組接口給它夕冲,那么該代理對(duì)象就默認(rèn)實(shí)現(xiàn)了該接口,這樣就能調(diào)用這組接口中的方法
// 參數(shù)3:指定InvocationHandler對(duì)象裂逐。即動(dòng)態(tài)代理對(duì)象在調(diào)用方法時(shí)歹鱼,會(huì)關(guān)聯(lián)到哪個(gè)InvocationHandler對(duì)象
...
// 僅貼出核心代碼
// 1. 通過 為Proxy類指定類加載器對(duì)象 & 一組interface,從而創(chuàng)建動(dòng)態(tài)代理類
// >>關(guān)注3
Class cl = getProxyClass(loader, interfaces);
// 2. 通過反射機(jī)制獲取動(dòng)態(tài)代理類的構(gòu)造函數(shù)卜高,其參數(shù)類型是調(diào)用處理器接口類型
Constructor cons = cl.getConstructor(constructorParams);
// 3. 通過動(dòng)態(tài)代理類的構(gòu)造函數(shù) 創(chuàng)建 代理類實(shí)例(傳入調(diào)用處理器對(duì)象
return (Object) cons.newInstance(new Object[] { h });
// 特別注意
// 1. 動(dòng)態(tài)代理類繼承 Proxy 類 & 并實(shí)現(xiàn)了在Proxy.newProxyInstance()中提供的一系列接口(接口數(shù)組)
// 2. Proxy 類中有一個(gè)映射表
// 映射關(guān)系為:(<ClassLoader>,(<Interfaces>,<ProxyClass>) )
// 即:1級(jí)key = 類加載器弥姻,根據(jù)1級(jí)key 得到 2級(jí)key = 接口數(shù)組
// 因此:1類加載器對(duì)象 + 1接口數(shù)組 = 確定了一個(gè)代理類實(shí)例
...
// 回到調(diào)用關(guān)注2的原處
}
<-- 關(guān)注3:getProxyClass()源碼分析 -->
// 作用:創(chuàng)建動(dòng)態(tài)代理類
public static Class<?> getProxyClass(ClassLoader loader,Class<?>... interfaces)
throws IllegalArgumentException {
...
// 僅貼出關(guān)鍵代碼
<-- 1. 將目標(biāo)類所實(shí)現(xiàn)的接口加載到內(nèi)存中 -->
// 遍歷目標(biāo)類所實(shí)現(xiàn)的接口
for (int i = 0; i < interfaces.length; i++) {
// 獲取目標(biāo)類實(shí)現(xiàn)的接口名稱
String interfaceName = interfaces[i].getName();
Class interfaceClass = null;
try {
// 加載目標(biāo)類實(shí)現(xiàn)的接口到內(nèi)存中
interfaceClass = Class.forName(interfaceName, false, loader);
} catch (ClassNotFoundException e) {
}
if (interfaceClass != interfaces[i]) {
throw new IllegalArgumentException(
interfaces[i] + " is not visible from class loader");
}
}
<-- 2. 生成動(dòng)態(tài)代理類 -->
// 根據(jù)傳入的接口 & 代理對(duì)象 創(chuàng)建動(dòng)態(tài)代理類的字節(jié)碼
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces);
// 根據(jù)動(dòng)態(tài)代理類的字節(jié)碼 生成 動(dòng)態(tài)代理類
proxyClass = defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
}
// 最終返回動(dòng)態(tài)代理類
return proxyClass;
}
// 回到調(diào)用關(guān)注3的原處
總結(jié)
- 通過調(diào)用處理器類對(duì)象的
.newProxyInstance()
創(chuàng)建動(dòng)態(tài)代理類 及其實(shí)例對(duì)象(需傳入目標(biāo)類對(duì)象) - 具體過程如下:
- 通過 為
Proy
類指定類加載器對(duì)象 & 一組接口,從而創(chuàng)建動(dòng)態(tài)代理類的字節(jié)碼掺涛;再根據(jù)類字節(jié)碼創(chuàng)建動(dòng)態(tài)代理類 - 通過反射機(jī)制獲取動(dòng)態(tài)代理類的構(gòu)造函數(shù)(參數(shù)類型 = 調(diào)用處理器接口類型
- 通過動(dòng)態(tài)代理類的構(gòu)造函數(shù) 創(chuàng)建 代理類實(shí)例(傳入調(diào)用處理器對(duì)象
- 通過 為
4.2 (關(guān)注2)通過調(diào)用動(dòng)態(tài)代理對(duì)象方法從而調(diào)用目標(biāo)對(duì)象方法
即庭敦,如何通過調(diào)用動(dòng)態(tài)代理對(duì)象方法,從而調(diào)用目標(biāo)對(duì)象方法薪缆?
// 使用代碼
Buyer1_DynamicProxy.buybuybuy();
- 在關(guān)注1中的
DynamicProxy.newProxyInstance()
生成了一個(gè)動(dòng)態(tài)代理類 及其實(shí)例
該動(dòng)態(tài)代理類記為 :
$Proxy0
下面我們直接看該類實(shí)現(xiàn)及其 buybuybuy()
- 該方法的邏輯如下:
<-- 動(dòng)態(tài)代理類 $Proxy0 實(shí)現(xiàn)-->
// 繼承:Java 動(dòng)態(tài)代理機(jī)制的主類:java.lang.reflect.Proxy
// 實(shí)現(xiàn):與目標(biāo)對(duì)象一樣的接口(即上文例子的Subject接口)
public final class $Proxy0 extends Proxy implements Subject {
// 構(gòu)造函數(shù)
public ProxySubject(InvocationHandler invocationhandler)
{
super(invocationhandler);
}
// buybuybuy()是目標(biāo)對(duì)象實(shí)現(xiàn)接口(Subject)中的方法
// 即$Proxy0類必須實(shí)現(xiàn)
// 所以在使用動(dòng)態(tài)代理類對(duì)象時(shí)秧廉,才可以調(diào)用目標(biāo)對(duì)象的同名方法(即上文的buybuybuy())
public final void buybuybuy() {
try {
super.h.invoke(this, m3, null);
// 該方法的邏輯實(shí)際上是調(diào)用了父類Proxy類的h參數(shù)的invoke()
// h參數(shù)即在Proxy.newProxyInstance(ClassLoader loader, Class<?>[]interfaces,InvocationHandler h)傳入的第3個(gè)參數(shù)InvocationHandler對(duì)象
// 即調(diào)用了調(diào)用處理器的InvocationHandler.invoke()
// 而復(fù)寫的invoke()利用反射機(jī)制:Object result=method.invoke(proxied,args)
// 從而調(diào)用目標(biāo)對(duì)象的的方法 ->>關(guān)注4
return;
} catch (Error e) {
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
<-- 關(guān)注4:調(diào)用處理器 類復(fù)寫的invoke() -->
// 即步驟1中實(shí)現(xiàn)的類:DynamicProxy
// 內(nèi)容很多都分析過了,直接跳到復(fù)寫的invoke()中
public class DynamicProxy implements InvocationHandler {
private Object ProxyObject;
public Object newProxyInstance(Object ProxyObject){
this.ProxyObject =ProxyObject;
return Proxy.newProxyInstance(ProxyObject.getClass().getClassLoader(),
ProxyObject.getClass().getInterfaces(),this);
}
// 復(fù)寫InvocationHandler接口的invoke()
// 動(dòng)態(tài)代理對(duì)象調(diào)用目標(biāo)對(duì)象的任何方法前拣帽,都會(huì)調(diào)用調(diào)用處理器類的invoke()
@Override
public Object invoke(Object proxy, Method method, Object[] args)
// 參數(shù)說(shuō)明:
// 參數(shù)1:動(dòng)態(tài)代理對(duì)象(即哪個(gè)動(dòng)態(tài)代理對(duì)象調(diào)用了method()
// 參數(shù)2:目標(biāo)對(duì)象被調(diào)用的方法
// 參數(shù)3:指定被調(diào)用方法的參數(shù)
throws Throwable {
System.out.println("代購(gòu)出門了");
Object result = null;
// 通過Java反射機(jī)制調(diào)用目標(biāo)對(duì)象方法
result = method.invoke(ProxyObject, args);
return result;
}
總結(jié)
- 動(dòng)態(tài)代理類實(shí)現(xiàn)了與目標(biāo)類一樣的接口疼电,并實(shí)現(xiàn)了需要目標(biāo)類對(duì)象需要調(diào)用的方法
- 該方法的實(shí)現(xiàn)邏輯 = 調(diào)用父類
Proxy
類的h.invoke()
其中h參數(shù) = 在創(chuàng)建動(dòng)態(tài)代理實(shí)例中
newProxyInstance(ClassLoader loader, Class<?>[]interfaces,InvocationHandler h)
傳入的第3個(gè)參數(shù)InvocationHandler
對(duì)象
- 在
InvocationHandler.invoke()
中通過反射機(jī)制,從而調(diào)用目標(biāo)類對(duì)象的方法
4.3 原理總結(jié)
我用一張圖總結(jié)第4節(jié)說(shuō)的關(guān)于動(dòng)態(tài)代理模式的源碼分析减拭。
至此蔽豺,關(guān)于代理模式中的動(dòng)態(tài)代理模式的相關(guān)知識(shí)已經(jīng)講解完畢。
5. 總結(jié)
我用兩張圖總結(jié)整篇文章的內(nèi)容
- 本文主要對(duì)動(dòng)態(tài)代理模式進(jìn)行了全面介紹
- 接下來(lái)我會(huì)對(duì)每種設(shè)計(jì)模式進(jìn)行詳細(xì)的分析拧粪,歡迎關(guān)注Carson_Ho的簡(jiǎn)書修陡,不定期分享關(guān)于安卓開發(fā)的干貨,追求短既们、平濒析、快,但卻不缺深度啥纸。
請(qǐng)點(diǎn)贊号杏!因?yàn)槟愕墓膭?lì)是我寫作的最大動(dòng)力!
相關(guān)文章閱讀
這是一份全面 & 詳細(xì)的設(shè)計(jì)模式學(xué)習(xí)指南
Carson帶你學(xué)設(shè)計(jì)模式:?jiǎn)卫J剑⊿ingleton)
Carson帶你學(xué)設(shè)計(jì)模式:簡(jiǎn)單工廠模式(SimpleFactoryPattern)
Carson帶你學(xué)設(shè)計(jì)模式:工廠方法模式(Factory Method)
Carson帶你學(xué)設(shè)計(jì)模式:抽象工廠模式(Abstract Factory)
Carson帶你學(xué)設(shè)計(jì)模式:策略模式(Strategy Pattern)
Carson帶你學(xué)設(shè)計(jì)模式:適配器模式(Adapter Pattern)
Carson帶你學(xué)設(shè)計(jì)模式:靜態(tài)代理模式(Proxy Pattern)
Carson帶你學(xué)設(shè)計(jì)模式:動(dòng)態(tài)代理模式(Proxy Pattern)
Carson帶你學(xué)設(shè)計(jì)模式:模板方法模式(Template Method)
Carson帶你學(xué)設(shè)計(jì)模式:建造者模式(Builder Pattern)
Carson帶你學(xué)設(shè)計(jì)模式:外觀模式(Facade Pattern)
Carson帶你學(xué)設(shè)計(jì)模式:觀察者模式(Observer)