靜態(tài)代理和動態(tài)代理

代理是一種軟件設(shè)計模式,目的是通過不直接調(diào)用被代理對象而訪問其方法,提高代碼重用率砍艾。

一般用于框架本身處理多種業(yè)務(wù)邏輯時,通過代理機制方便業(yè)務(wù)方調(diào)用巍举,也利于框架的拓展和解耦脆荷。在代碼編譯時就確定目標(biāo)類是哪個,可用靜態(tài)代理。動態(tài)代理是在代碼運行時加載目標(biāo)類蜓谋。

靜態(tài)代理步驟:

  1. 目標(biāo)類和代理類都實現(xiàn)相同的業(yè)務(wù)接口梦皮;
  2. 代理類的構(gòu)造方法中傳入目標(biāo)類的實例;
  3. 在代理類的接口實現(xiàn)中調(diào)用目標(biāo)類實例的接口方法桃焕;

靜態(tài)代理的缺點是不同的業(yè)務(wù)剑肯,需要實現(xiàn)多個目標(biāo)實現(xiàn)類,代碼冗余高观堂。

動態(tài)代理原理:
動態(tài)代理中涉及到InvocationHandler接口和Proxy類让网。

Proxy類的newProxyInstance()方法負(fù)責(zé)代理類實例的創(chuàng)建。

  public static Object newProxyInstance(
      ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
  • ClassLoader loader:指定一個動態(tài)加載代理類的類加載器师痕。
  • Class<?>[] interfaces:指明目標(biāo)類實現(xiàn)的接口溃睹。
  • InvocationHandler h:方法委托類。

Proxy類與普通類的唯一區(qū)別就是其字節(jié)碼是由 JVM 在運行時動態(tài)生成的而非預(yù)存在于任何一個 .class 文件中胰坟。

InvocationHandler的接口方法是invoke()因篇,通過代理類調(diào)用目標(biāo)類方法時,最終都會委托此方法執(zhí)行笔横。

public interface InvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args) 
        throws Throwable;
}
  • Object proxy:代理類實例
  • Method method:調(diào)用的方法對象
  • Object[] args:調(diào)用的參數(shù)

一般會在此方法前后增加一些操作竞滓,對某個業(yè)務(wù)流程補充完善子流程,即面向切面編程(AOP)吹缔。

面向切面編程(AOP):是在一系列縱向的控制流程中商佑,把那些相同的子流程提取成一個橫向的面。即通過預(yù)編譯方式和運行期動態(tài)代理涛菠,實現(xiàn)在不修改源代碼的情況下給程序統(tǒng)一添加功能的技術(shù)思想莉御。

動態(tài)代理步驟:

  1. 創(chuàng)建目標(biāo)業(yè)務(wù)接口和實現(xiàn)類實例;
  2. 通過Proxy類的newProxyInstance()方法獲取代理類實例俗冻;
  3. 創(chuàng)建InvocationHandler方法委托類實例,實現(xiàn)代理類到目標(biāo)類的方法分派牍颈,并支持在目標(biāo)類業(yè)務(wù)前后增改操作迄薄;

目標(biāo)類及其接口 示例如下:

/**
 * 目標(biāo)業(yè)務(wù)接口
 */
public interface IProxy {
    void print();
}

/**
 * 目標(biāo)類——實現(xiàn)目標(biāo)業(yè)務(wù)接口
 */
public class MyProxy implements IProxy {
    @Override
    public void print() {
        Log.d("test","面向AOP編程——進行中");
    }
}

方法委托類 示例如下:

/**
 * 方法委托類——實現(xiàn)InvocationHandler接口
 */
public class MyInvocationHandler implements InvocationHandler {
    private MyProxy myProxy;

    /**
     * 通過構(gòu)造器注入被目標(biāo)類實例
     * @param myProxy
     */
    public MyInvocationHandler(MyProxy myProxy) {
        this.myProxy = myProxy;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Log.d("test", "面向AOP編程——準(zhǔn)備中");//模擬前置操作
        Object object = method.invoke(this.myProxy, args);//通過反射調(diào)用目標(biāo)類方法
        Log.d("test", "面向AOP編程——結(jié)束后");//模擬后置操作
        return object;
    }
}

外部框架調(diào)用目標(biāo)類 示例如下:

private void testProxy() {
     MyProxy myProxy = new MyProxy();
     IProxy iProxy = (IProxy) Proxy.newProxyInstance(
             Thread.currentThread().getContextClassLoader(),
             myProxy.getClass().getInterfaces(),
             new MyInvocationHandler(myProxy));
     iProxy.print();
}

ClassLoader是類裝載器,將類的字節(jié)碼裝載到 Java 虛擬機(JVM)中并為其定義類對象煮岁,然后該類才能被使用讥蔽。 因此每次生成動態(tài)代理類對象時都需要指定一個類裝載器對象。

打印log如下:

D/test: 面向AOP編程——準(zhǔn)備中
D/test: 面向AOP編程——進行中
D/test: 面向AOP編程——結(jié)束后
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末画机,一起剝皮案震驚了整個濱河市冶伞,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌步氏,老刑警劉巖响禽,帶你破解...
    沈念sama閱讀 217,084評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡芋类,警方通過查閱死者的電腦和手機隆嗅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來侯繁,“玉大人胖喳,你說我怎么就攤上這事≈梗” “怎么了丽焊?”我有些...
    開封第一講書人閱讀 163,450評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長咕别。 經(jīng)常有香客問我技健,道長,這世上最難降的妖魔是什么顷级? 我笑而不...
    開封第一講書人閱讀 58,322評論 1 293
  • 正文 為了忘掉前任凫乖,我火速辦了婚禮,結(jié)果婚禮上弓颈,老公的妹妹穿的比我還像新娘帽芽。我一直安慰自己,他們只是感情好翔冀,可當(dāng)我...
    茶點故事閱讀 67,370評論 6 390
  • 文/花漫 我一把揭開白布导街。 她就那樣靜靜地躺著,像睡著了一般纤子。 火紅的嫁衣襯著肌膚如雪搬瑰。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,274評論 1 300
  • 那天控硼,我揣著相機與錄音搀捷,去河邊找鬼。 笑死副渴,一個胖子當(dāng)著我的面吹牛信卡,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播幔妨,決...
    沈念sama閱讀 40,126評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼鹦赎,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了误堡?” 一聲冷哼從身側(cè)響起古话,我...
    開封第一講書人閱讀 38,980評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎锁施,沒想到半個月后陪踩,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體杖们,經(jīng)...
    沈念sama閱讀 45,414評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,599評論 3 334
  • 正文 我和宋清朗相戀三年膊毁,在試婚紗的時候發(fā)現(xiàn)自己被綠了胀莹。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,773評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡婚温,死狀恐怖描焰,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情栅螟,我是刑警寧澤荆秦,帶...
    沈念sama閱讀 35,470評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站力图,受9級特大地震影響步绸,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜吃媒,卻給世界環(huán)境...
    茶點故事閱讀 41,080評論 3 327
  • 文/蒙蒙 一瓤介、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧赘那,春花似錦刑桑、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至拱礁,卻和暖如春琢锋,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背呢灶。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評論 1 269
  • 我被黑心中介騙來泰國打工吴超, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人鸯乃。 一個月前我還...
    沈念sama閱讀 47,865評論 2 370
  • 正文 我出身青樓烛芬,卻偏偏與公主長得像,于是被迫代替她去往敵國和親飒责。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,689評論 2 354

推薦閱讀更多精彩內(nèi)容