Proxy.newProxyInstance

簡(jiǎn)單實(shí)現(xiàn)

Q:通過(guò)代理接口的方式進(jìn)行聲明, 然而不通過(guò)類實(shí)現(xiàn)的方式進(jìn)行使用,而是使用其他方式實(shí)現(xiàn).
比如MyBatis 如何做到只定義接口, 邏輯寫到xml中,就可以調(diào)用接口?
FeignClient 為什么只做了聲明,卻可以直接使用接口進(jìn)行注入?

A: 其實(shí)這些底層都是用于了一個(gè)叫做代理的方式來(lái)實(shí)現(xiàn)的

比如 現(xiàn)在有一個(gè)接口是這樣的


    interface TestInterface {

        String test01();

        String test02(String st, String st2);

    }

借助 代理的方式給他提供方法的實(shí)現(xiàn),需要用到 Proxy.newProxyInstance這個(gè)方法

newProxyInstance侵佃,方法有三個(gè)參數(shù):

  1. loader : 用哪個(gè)類加載器去加載代理對(duì)象
  2. interfaces: 動(dòng)態(tài)代理類需要實(shí)現(xiàn)的接口
  3. h: InvocationHandler 類型 動(dòng)態(tài)代理方法在執(zhí)行時(shí),會(huì)調(diào)用h里面的invoke方法去執(zhí)行

loader實(shí)例很好獲得, 使用getClass().getClassLoader()即可.

現(xiàn)在來(lái)構(gòu)造一個(gè) interfaces的實(shí)例

 new Class[]{TestInterface.class}

構(gòu)造一個(gè) h的對(duì)象

    static class TestProxy implements InvocationHandler {
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

          return null;
        }

動(dòng)態(tài)創(chuàng)建一個(gè)接口的實(shí)例


        InvocationHandler h = new TestProxy();

        TestInterface obj = (TestInterface) Proxy.newProxyInstance(getClass().getClassLoader(), 
                                  new Class[]{TestInterface.class}, h);

以上,就完成了大概調(diào)用的編寫. 接著來(lái)完成接口實(shí)現(xiàn).

完善TestProxy.invoke方法


        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 假設(shè)這里按照不同的需求進(jìn)行了實(shí)現(xiàn). 
            switch (method.getName()) {
                case "tet01": {
                    return "invoke==>" + UUID.randomUUID().toString();
                }
                case "test02": {
                    return "invoke==>" + Arrays.asList(args);
                }
            }
            return null;

        }
    }

完成 方法的調(diào)用


     InvocationHandler h = new TestProxy();

        TestInterface obj = (TestInterface) Proxy.newProxyInstance(getClass().getClassLoader(),
                   new Class[]{TestInterface.class}, h);

      //調(diào)用接口中的方法.
        String res = obj.test01();

        System.out.println(res);

簡(jiǎn)單的封裝

創(chuàng)建一個(gè)工廠

    static class TestFactory {

        public static <T> T newInstance(Class<T> clazz) {

            InvocationHandler h = new TestProxy();

            return (T) Proxy.newProxyInstance(TestFactory.class.getClassLoader(), new Class[]{clazz}, h);
        }

    }

通過(guò)工廠來(lái)調(diào)用

        TestInterface t = TestFactory.newInstance(TestInterface.class);

        String res = t.test02("111", "222");

        System.out.println(res);

完整的測(cè)試類

import org.junit.Test;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.UUID;

public class TestProxyClazz {

    interface TestInterface {

        String test01();

        String test02(String st, String st2);

    }


    static class TestProxy implements InvocationHandler {
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

            switch (method.getName()) {
                case "tet01": {
                    return "invoke==>" + UUID.randomUUID().toString();
                }
                case "test02": {
                    return "invoke==>" + Arrays.asList(args);
                }
            }
            return null;

        }
    }

    static class TestFactory {

        public static <T> T newInstance(Class<T> clazz) {

            InvocationHandler h = new TestProxy();


            return (T) Proxy.newProxyInstance(TestFactory.class.getClassLoader(), new Class[]{clazz}, h);
        }

    }

    @Test
    public void tet01() {

        InvocationHandler h = new TestProxy();

        TestInterface obj = (TestInterface) Proxy.newProxyInstance(getClass().getClassLoader(),
 new Class[]{TestInterface.class}, h);

        String res = obj.test01();

        System.out.println(res);

    }

    @Test
    public void tet02() {

        TestInterface t = TestFactory.newInstance(TestInterface.class);

        String res = t.test02("111", "222");

        System.out.println(res);

    }
}

總結(jié)

通過(guò)這種代理方式,可以很輕松做到動(dòng)態(tài)創(chuàng)建接口實(shí)現(xiàn)類.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請(qǐng)通過(guò)簡(jiǎn)信或評(píng)論聯(lián)系作者劫恒。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市匙奴,隨后出現(xiàn)的幾起案子浮声,更是在濱河造成了極大的恐慌,老刑警劉巖赋铝,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件插勤,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡革骨,警方通過(guò)查閱死者的電腦和手機(jī)农尖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)良哲,“玉大人盛卡,你說(shuō)我怎么就攤上這事≈欤” “怎么了滑沧?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵并村,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我滓技,道長(zhǎng)哩牍,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任殖属,我火速辦了婚禮姐叁,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘洗显。我一直安慰自己外潜,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布挠唆。 她就那樣靜靜地躺著处窥,像睡著了一般。 火紅的嫁衣襯著肌膚如雪玄组。 梳的紋絲不亂的頭發(fā)上滔驾,一...
    開(kāi)封第一講書(shū)人閱讀 48,970評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音俄讹,去河邊找鬼哆致。 笑死,一個(gè)胖子當(dāng)著我的面吹牛患膛,可吹牛的內(nèi)容都是我干的摊阀。 我是一名探鬼主播,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼踪蹬,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼胞此!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起跃捣,我...
    開(kāi)封第一講書(shū)人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤漱牵,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后疚漆,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體酣胀,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年娶聘,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了闻镶。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡趴荸,死狀恐怖儒溉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情发钝,我是刑警寧澤顿涣,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布波闹,位于F島的核電站,受9級(jí)特大地震影響涛碑,放射性物質(zhì)發(fā)生泄漏精堕。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一蒲障、第九天 我趴在偏房一處隱蔽的房頂上張望歹篓。 院中可真熱鬧,春花似錦揉阎、人聲如沸庄撮。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)洞斯。三九已至,卻和暖如春坑赡,著一層夾襖步出監(jiān)牢的瞬間烙如,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來(lái)泰國(guó)打工毅否, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留亚铁,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓螟加,卻偏偏與公主長(zhǎng)得像徘溢,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子仰迁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

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