JDK 動態(tài)代理 應(yīng)用

動態(tài)代理的思想來源于 代理模式
本片文章不講述設(shè)計模式,需要學(xué)習(xí)設(shè)計模型知識請自行查閱資料.

被代理類

JDK動態(tài)代理要求被代理類只能是接口或者實現(xiàn)某接口的類。
此處定義被代理接口

public interface BeProxyInterface {

    /**
     * 聲明被代理方法
     * @param msg 參數(shù)
     * @return
     */
    Object call(String msg);
}

代理類

我更喜歡把代理類叫做 觸發(fā)控制類,因為代理類必須要實現(xiàn)InvocationHandler

public class Advised implements InvocationHandler {

    /**
     * 觸發(fā)被代理的方法
     * @param proxy         代理對象
     * @param method        當(dāng)前觸發(fā)的方法
     * @param objects       當(dāng)前觸發(fā)方法的入?yún)?     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] objects) throws Throwable {
        System.out.println("-------觸發(fā)了方法-------");
        return null;
    }
}

創(chuàng)建代理對象

Object proxy = Proxy.newProxyInstance(BeProxyInterface.class.getClassLoader(), new Class[] {BeProxyInterface.class}, new Advised());
 BeProxyInterface proxyObj = (BeProxyInterface)proxy;
proxyObj.call("哈哈");

以上,給BeProxyInteface接口生成了一個代理對象看峻∈亢基本就是動態(tài)代理的使用.

不過你可能會說狸页,以上示例只是打印了一行輸出路捧,沒有實際用處.

沒錯撒顿,以上示例確實沒什么實際用處丑罪,不過還是能擴(kuò)展,使其能得到真正應(yīng)用凤壁。
說到真正應(yīng)用之前吩屹,先看看網(wǎng)上其他文章可能給出的一般用法。
一般用法是觸發(fā)控制類持有被代理對象真實示例.并觸發(fā)被代理對象的方法. 如下

public class Advised implements InvocationHandler {
    private BeProxyInterface beProxyInterface;
    @Override
    public Object invoke(Object proxy, Method method, Object[] objects) throws Throwable {
        method.invoke(beProxyInterface, objects);
  }
}

對應(yīng)的創(chuàng)建代理類的修改, 需要指定拧抖。
以上示例是比較常見的示例煤搜。 實際上像spring的動態(tài)代理也是這種方式,BeProxyInterface對應(yīng)的就是spring的bean(targetSource); InvocationHanderl關(guān)聯(lián)的BeProxyInterface改為關(guān)聯(lián)beanName唧席。

模板配置使用

這里展示一種之前說的真實用法擦盾。就是把InvocationHander當(dāng)成模板,被代理對象當(dāng)成可變配置使用淌哟。

可能的使用場景

消息隊列發(fā)送消息

一般的迹卢,往消息隊列方式消息,需要指定消息對象绞绒,以及接收的隊列就可以婶希。發(fā)送方法是可以公用的。即連接隊列發(fā)送消息蓬衡,連接對象可以公用喻杈,需要提供消息體和隊列名詞即可。

  • 定義接口狰晚,指定消息隊列筒饰,并指定消息對象
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface RabbitMqProducer {

    String exchange();

    String routing();
}
public interface BeProxyInterface {
    /**
     * 聲明被代理方法
     * @param msg 參數(shù)
     * @return
     */
    @RabbitMqProducer(exchange = "exchange.test.topic", routing = "routing.test")
    Object call(String msg);
}
  • 實現(xiàn)發(fā)送消息模板
public class Advised implements InvocationHandler {

    /**
     * 觸發(fā)被代理的方法
     * @param proxy         代理對象
     * @param method        代理對上當(dāng)前觸發(fā)的方法
     * @param objects       當(dāng)前觸發(fā)方法的入?yún)?     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] objects) throws Throwable {
        System.out.println("-------觸發(fā)了方法-------");
        RabbitMqProducer rabbitMqProducer = method.getAnnotation(RabbitMqProducer.class);
        if (rabbitMqProducer != null) {
            String exchange = rabbitMqProducer.exchange();
            String routing = rabbitMqProducer.routing();
            System.out.println("根據(jù)exchange:" + exchange + ", routing:" + routing + ", 發(fā)送消息 :" + objects[0]);
        }
        return null;
    }
}
  • 發(fā)送消息
public static void main(String[] args) {
        Object proxy = Proxy.newProxyInstance(BeProxyInterface.class.getClassLoader(), new Class[] {BeProxyInterface.class}, new Advised());
        BeProxyInterface proxyObj = (BeProxyInterface)proxy;
        proxyObj.call("哈哈");
    }

輸出結(jié)果

-------觸發(fā)了方法-------
根據(jù)exchange:exchange.test.topic, routing:routing.test, 發(fā)送消息 :哈哈

以上,把觸發(fā)控制類當(dāng)模板來用壁晒。 要把消息發(fā)送到不通隊列瓷们,則只需要寫不同的BeProxyInterface接口即可。

總結(jié)

JDK動態(tài)代理,提供了運行時創(chuàng)建代理的能力。根據(jù)代理特性谬晕,可以擴(kuò)展其用法碘裕,不僅僅是代理的任務(wù)上。因為代理的本身是生成對象攒钳。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末帮孔,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子不撑,更是在濱河造成了極大的恐慌文兢,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件焕檬,死亡現(xiàn)場離奇詭異姆坚,居然都是意外死亡,警方通過查閱死者的電腦和手機实愚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進(jìn)店門兼呵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人爆侣,你說我怎么就攤上這事萍程。” “怎么了兔仰?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蕉鸳。 經(jīng)常有香客問我乎赴,道長,這世上最難降的妖魔是什么潮尝? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任榕吼,我火速辦了婚禮,結(jié)果婚禮上勉失,老公的妹妹穿的比我還像新娘羹蚣。我一直安慰自己,他們只是感情好乱凿,可當(dāng)我...
    茶點故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布顽素。 她就那樣靜靜地躺著,像睡著了一般徒蟆。 火紅的嫁衣襯著肌膚如雪胁出。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天段审,我揣著相機與錄音全蝶,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛抑淫,可吹牛的內(nèi)容都是我干的绷落。 我是一名探鬼主播,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼始苇,長吁一口氣:“原來是場噩夢啊……” “哼砌烁!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起埂蕊,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤往弓,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后蓄氧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體函似,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年喉童,在試婚紗的時候發(fā)現(xiàn)自己被綠了撇寞。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡堂氯,死狀恐怖蔑担,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情咽白,我是刑警寧澤啤握,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站晶框,受9級特大地震影響排抬,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜授段,卻給世界環(huán)境...
    茶點故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一蹲蒲、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧侵贵,春花似錦届搁、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蔫骂,卻和暖如春么翰,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背辽旋。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工浩嫌, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留檐迟,地道東北人。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓码耐,卻偏偏與公主長得像追迟,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子骚腥,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,834評論 2 345

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