設(shè)計(jì)模式-動(dòng)態(tài)代理模式

之前介紹了代理模式,大家也都了解了代理模式,不過(guò)之前介紹的代理模式是靜態(tài)代理,靜態(tài)代理什么意思锐墙?靜態(tài)代理指的是代理類(lèi)是事先定義好的,在使用代理類(lèi)的時(shí)候也是明確初始化定義的代理類(lèi)长酗。但是如果有非常多的類(lèi)需要代理溪北,那么一個(gè)個(gè)那么定義靜態(tài)代理類(lèi)的工作量將是非常大的,其實(shí)JDK已經(jīng)給我們提供了現(xiàn)成的動(dòng)態(tài)代理類(lèi)夺脾,可以不用事先定義好所有的代理類(lèi)之拨,下面我們就介紹下JDK動(dòng)態(tài)代理類(lèi)。

JDK中動(dòng)態(tài)代理主要涉及到的是兩個(gè)類(lèi):java.lang.reflect.InvocationHandler和java.lang.reflect.Proxy劳翰。下面我們先定義一下Subject接口和兩個(gè)功能一樣的實(shí)現(xiàn)類(lèi)用于測(cè)試敦锌。

Subject.java 接口類(lèi)

public interface Subject {
    public String doSomething(String name);
}

RealSubject.java 實(shí)際提供功能的類(lèi)

public class RealSubject implements Subject {
    @Override
    public String doSomething(String name) {
        System.out.println(name + " do something!");
        return name + " do something!";
    }
}

需要實(shí)現(xiàn)動(dòng)態(tài)代理功能的話實(shí)現(xiàn)一個(gè)代理類(lèi)實(shí)現(xiàn)InvocationHandler的接口,并實(shí)現(xiàn)invoke方法佳簸。

例子中實(shí)現(xiàn)DynamicProxyAOP類(lèi)用于在Subject類(lèi)前后分別實(shí)現(xiàn)其他功能乙墙,類(lèi)似AOP切面功能,其實(shí)Spring AOP的內(nèi)部核心實(shí)現(xiàn)就是通過(guò)動(dòng)態(tài)代理實(shí)現(xiàn)的生均√耄可以看到public Object invoke(Object proxy, Method method, Object[] args)方法有3個(gè)入?yún)ⅲ琾roxy表示代理類(lèi)马胧,method表示調(diào)用的Subject主類(lèi)的方法名汉买,args表示調(diào)用代理方法的參數(shù)數(shù)組,在內(nèi)部的具體實(shí)現(xiàn)我們通過(guò)反射方法通過(guò)method.invode來(lái)調(diào)用實(shí)際Subject方法佩脊。


public class DynamicProxyAOP implements InvocationHandler {
    private Object subject;

    public DynamicProxyAOP(Object subject) {
        this.subject = subject;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //在執(zhí)行真實(shí)subject執(zhí)行的方法
        System.out.println("before do something");
        //執(zhí)行真實(shí)subject方法
        Object rtn = method.invoke(subject, args);
        //在執(zhí)行結(jié)束后再執(zhí)行的方法
        System.out.println("after do something");

        return rtn;
    }
}

這樣就定義好了動(dòng)態(tài)代理的核心類(lèi)蛙粘,最后我們看下如何調(diào)用動(dòng)態(tài)代理類(lèi)。先分別定義RealSubject和RealSubject2兩個(gè)類(lèi)的對(duì)象威彰,再分別實(shí)現(xiàn)兩個(gè)DynamicProxyAOP的代理對(duì)象出牧,DynamicProxyAOP的入?yún)⒎謩e為這兩個(gè)Subject的對(duì)象。接下來(lái)我們創(chuàng)建動(dòng)態(tài)代理對(duì)象歇盼,通過(guò)調(diào)用Proxy的Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)來(lái)創(chuàng)建動(dòng)態(tài)代理對(duì)象舔痕,第一個(gè)參數(shù)為實(shí)現(xiàn)代理類(lèi)的ClassLoader,第二個(gè)參數(shù)為被代理類(lèi)的接口數(shù)組,最后一個(gè)參數(shù)為繼承自InvocationHandler的handler實(shí)現(xiàn)具體的代理功能伯复。

public class DynamicProxyMain {

    public static void main(String[] args){
        Subject realSubject = new RealSubject();
        Subject realSubject2 = new RealSubject2();

        InvocationHandler handler = new DynamicProxyAOP(realSubject);
        InvocationHandler handler2 = new DynamicProxyAOP(realSubject2);

        Subject subject = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(),
                realSubject.getClass().getInterfaces(),
                handler);

        Subject subject2 = (Subject) Proxy.newProxyInstance(realSubject2.getClass().getClassLoader(),
                realSubject2.getClass().getInterfaces(),
                handler2);

        String rtn = subject.doSomething("tester ");
        String rtn2 = subject2.doSomething("tester ");
    }
}

從打印出的日志可以發(fā)現(xiàn)慨代,定義了兩個(gè)不同的繼承自Subject的類(lèi),但是動(dòng)態(tài)代理對(duì)象是動(dòng)態(tài)創(chuàng)建的啸如,不需要像靜態(tài)代理那樣侍匙,再為每一個(gè)Subject實(shí)現(xiàn)類(lèi)創(chuàng)建代理類(lèi),是不是很方便组底,后續(xù)大家如果要自己實(shí)現(xiàn)一些切面功能丈积,就可以通過(guò)動(dòng)態(tài)代理模式來(lái)實(shí)現(xiàn)筐骇,例如紀(jì)錄日至之類(lèi)的债鸡。


before do something
tester  do something!
after do something
before do something
tester  do something2!
after do something

本文實(shí)例中的源碼:https://github.com/feiweiwei/designpattern

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市铛纬,隨后出現(xiàn)的幾起案子厌均,更是在濱河造成了極大的恐慌,老刑警劉巖告唆,帶你破解...
    沈念sama閱讀 217,185評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件棺弊,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡擒悬,警方通過(guò)查閱死者的電腦和手機(jī)模她,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)懂牧,“玉大人侈净,你說(shuō)我怎么就攤上這事∩铮” “怎么了畜侦?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,524評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)躯保。 經(jīng)常有香客問(wèn)我旋膳,道長(zhǎng),這世上最難降的妖魔是什么途事? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,339評(píng)論 1 293
  • 正文 為了忘掉前任验懊,我火速辦了婚禮,結(jié)果婚禮上尸变,老公的妹妹穿的比我還像新娘义图。我一直安慰自己,他們只是感情好振惰,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評(píng)論 6 391
  • 文/花漫 我一把揭開(kāi)白布歌溉。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪痛垛。 梳的紋絲不亂的頭發(fā)上草慧,一...
    開(kāi)封第一講書(shū)人閱讀 51,287評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音匙头,去河邊找鬼漫谷。 笑死,一個(gè)胖子當(dāng)著我的面吹牛蹂析,可吹牛的內(nèi)容都是我干的舔示。 我是一名探鬼主播,決...
    沈念sama閱讀 40,130評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼电抚,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼惕稻!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起蝙叛,我...
    開(kāi)封第一講書(shū)人閱讀 38,985評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤俺祠,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后借帘,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體蜘渣,經(jīng)...
    沈念sama閱讀 45,420評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評(píng)論 3 334
  • 正文 我和宋清朗相戀三年肺然,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蔫缸。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,779評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡际起,死狀恐怖拾碌,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情加叁,我是刑警寧澤倦沧,帶...
    沈念sama閱讀 35,477評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站它匕,受9級(jí)特大地震影響展融,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜豫柬,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評(píng)論 3 328
  • 文/蒙蒙 一告希、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧烧给,春花似錦燕偶、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,716評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)酝惧。三九已至,卻和暖如春伯诬,著一層夾襖步出監(jiān)牢的瞬間晚唇,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,857評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工盗似, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留哩陕,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,876評(píng)論 2 370
  • 正文 我出身青樓赫舒,卻偏偏與公主長(zhǎng)得像悍及,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子接癌,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評(píng)論 2 354

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