亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Java > 正文

java動態代理詳解

2019-11-26 15:39:01
字體:
來源:轉載
供稿:網友

代理都知道吧,你去買東西就有很多的代理商,他們就是賣原廠的東西。比如,你天天要買肉,豬是農民伯伯養的,但你是從屠夫手上買到肉的,這個屠夫就可以當成是代理。那為什么要代理呢,代理有什么用呢,當然是有事給他做了,對于屠夫這個代理就好理解了,因為你自己不可能去宰豬吧,所以代理就是去買活豬,然后宰掉再賣給你,當然屠夫有可能給肉注點水,關鍵看他壞不壞,所以屠夫的整個流程就是:

這個流程用代碼怎么實現呢:我們應該要用三個類You、Butcher、Farmer分別指你、屠夫、農民伯伯。其中農民伯伯又提供一個買肉的方法給屠夫調用,這個方法輸入是錢的數量,返回是肉的數量,都用int型,代碼如下:

復制代碼 代碼如下:

class Farmer {
    public int buyMeat(int money) {
        int meat = 0;
        // ... meat = ***;
        return meat;
    }
}

而屠夫則提供一個買肉的方法給你調用,同樣是輸入錢,返回肉,但是會把肉加工一下(殺豬和刮豬毛在代碼中就省了,要不然還得為豬寫個類),代碼如下:

復制代碼 代碼如下:

class Butcher {
    public int buyMeat(int money) {
        Farmer farmer = new Farmer();            // 1.find a farmer.
        int meat = farmer.buyMeat(money);        // 2.buy meat from the farmer.
        meat += 5;                               // 3.inject 5 pound water into the meat, so weight will increase.
        return meat;                             // 4.return to you.
    }
}

然你從屠夫手上買肉的代碼就變成這樣:

復制代碼 代碼如下:

class You {
    public void work() {
        int youMoney = 10;
        Butcher butcher = new Butcher();        // find a butcher.
        int meat = butcher.buyMeat(youMoney);
        System.out.println("Cook the meat, weight: " + meat);  // you cooked it. 
    }
}

這個程序我們還可以優化一下,我們發現屠夫有農民有一個相同的買肉方法,我們可以提取一個接口,叫為商販(pedlar)吧,以后你買肉就不用管他是屠夫還是農民伯伯了,只要他有肉賣就可以了,我們提取一個接口后,代碼就變成這樣:

復制代碼 代碼如下:

class You {
    public void work() {
        int youMoney = 10;
        Peldar peldar= new Butcher();                               // find a peldar.
        int meat = peldar.buyMeat(youMoney);
        System.out.println("Cook the meat, weight: " + meat);        // you cooked it.   
    }
}
interface Peldar {
 int buyMeat(int money);
}
class Butcher implements Peldar {
    @Override
    public int buyMeat(int money) {
        Farmer farmer = new Farmer();            // 1.find a farmer.
        int meat = farmer.buyMeat(money);        // 2.buy meat from the farmer.
        meat += 5;                               // 3.inject 5 pound water into the meat, so weight will increase.
        return meat;                             // 4.return to you.
    }
}

class Farmer implements Peldar {
    @Override
    public int buyMeat(int money) {
        int meat = 0;
        // ... meat = ***;
        return meat;
    }
}

這就是代理,值得注意的是一般代理類和最終類會實現同一接口,這樣的好處是,調用者就不用關心當前引用的到底是代理還是最終類。

不過這叫靜態代理,因為代理類(屠夫類)是你親手寫,動態代理就是Java在運行的時候,動態生成一個等價的代理類。雖然類是動態生成的,但是殺豬和注水的代碼還是要寫的,只是不要寫一個類了。寫到哪里呢,寫到下面這個接口里面:

復制代碼 代碼如下:

public interface InvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}

參數是什么意思呢,我寫成這樣,可能你就明白了:

復制代碼 代碼如下:

public interface InvocationHandler {
    public Object invoke(Object butcher, Method buyMeat, Object[] money) throws Throwable;
}

第一個參數是自動生成的代理類的一個對象(自動生成的屠夫類的對象),第二個參數是正前正在被調用的方法的對象(方法怎么還有對象呢,參見Java反射機制),我們這里只有一個方法叫buyMeat,所以這個參數代表的肯定就是它了,第三個參數是傳給前面那個方法的參數數組,buyMeat只有一個參數,所以這個數組只會有一個元素。于是殺豬注水的代碼寫進來就變成這樣了:

復制代碼 代碼如下:

InvocationHandler mInvocationHandler = new InvocationHandler() {  
    @Override
    public Object invoke(Object butcher, Method buyMeat, Object[] args) throws Throwable {
        Farmer farmer = new Farmer();              // 1.find a farmer.
        int meat = (Integer) buyMeat.invoke(farmer, args);      // 2.buy meat from the farmer.
        meat += 5;                                 // 3.inject 5 pound water into the meat, so weight will increase.
        return meat;                               // 4.return to you.
    }
};

這個里調用農民伯伯的買肉方法有點不符常規,這里是反射機制調用法,意思是這樣的,以farmer對象為接受者來調用buyMeat方法,跟直接調用farmer的方法是一樣的,你可能會問那為什么不直接調用呢,你可能沒注意,invoke的第一個參數類型是Object,所以你可以向任何對象發布調用命令(但不一定會成功,什么時候會成功等下說),如果你有很多farmer對象,甚至不是farmer對象,只要某接口的實例就可以(哪個接口等下說明,我們先命名為A接口),就可以當成參數傳進來,然后對其進行方法調用。現在我們來看看如何生成代理類吧,很簡單,可以調用Proxy的工廠方法,如下:

復制代碼 代碼如下:

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) 
    throws IllegalArgumentException

解釋參數,第一個ClassLoader是用來加載代理類的(關于ClassLoader,本文暫不講解),你暫不了解也沒關系,第二個是一個數組,每個元數都是一個接口,新生成的代理都會實現所有這些接口,傳給InvocationHandler.invoke第二個參數的方法,必定屬于所有這些接口中的方法,上一段落說的那個A接口必須是數組中的一個元素,上一段落說的那個調用成失敗問題也明了了。第三個參數InvocationHandler更好理解了,就是只要代理類中的任何方法被調用,就會通知這個InvocationHandler。下面寫出完整代碼:

復制代碼 代碼如下:

class You {
    public void work() {
        int youMoney = 10;

        Peldar peldarProxy = (Peldar) Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{Peldar.class}, mInvocationHandler);
        int meat = peldarProxy.buyMeat(youMoney);

        System.out.println("Cook the meat, weight: " + meat);   
    }

    InvocationHandler mInvocationHandler = new InvocationHandler() {       
        @Override
        public Object invoke(Object butcher, Method buyMeat, Object[] args)
                throws Throwable {
            Farmer farmer = new Farmer();                           // 1.find a farmer.
            int meat = (Integer) buyMeat.invoke(farmer, args);      // 2.buy meat from the farmer.
            meat += 5;                                              // 3.inject 5 pound water into the meat, so weight will increase.
            return meat;                                            // 4.return to you.
        }
    };

}
interface Peldar {
    int buyMeat(int money);
}

class Farmer implements Peldar {
    @Override
    public int buyMeat(int money) {
        int meat = 0;
        // ... meat = ***;
        return meat;
    }
}

這里You類里生成一個代理類,在代理類的buyMeat被調用時,代碼就跟之前的靜態代理一樣的了。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
正在播放欧美视频| 日韩欧美国产高清91| 久久综合色影院| 国产人妖伪娘一区91| 国产精品www| 福利一区福利二区微拍刺激| 亚洲国产精品久久精品怡红院| 亚洲精品自拍视频| 欧美一区二三区| 国产日韩欧美在线看| 亚洲国产一区二区三区在线观看| 成人性生交大片免费看小说| 欧美日韩国产精品| 欧美与欧洲交xxxx免费观看| 欧美做受高潮电影o| 91精品久久久久久久久久久久久| 久久香蕉国产线看观看av| 精品电影在线观看| 欧美一级大片在线观看| www.欧美精品| 久久视频在线直播| 久久精品国产精品| 精品视频在线观看日韩| 羞羞色国产精品| 日韩中文字幕视频在线| 欧美在线观看网站| 青青草成人在线| 久久99亚洲精品| 久久免费视频网站| 久久影院资源站| 国产精品美女主播| 日韩在线观看免费| 欧美日韩久久久久| 国产香蕉精品视频一区二区三区| 久久久久久久999精品视频| 俺去啦;欧美日韩| 91大神福利视频在线| 国产在线999| 亚洲欧美日韩精品久久奇米色影视| 欧美黑人视频一区| 欧美日韩成人在线视频| 久久中文字幕在线视频| 国产精品久久一区主播| 久久午夜a级毛片| 国产精品免费视频xxxx| 日韩电影在线观看永久视频免费网站| 亚洲高清一区二| 成人午夜激情网| 亚洲精品综合久久中文字幕| 日本亚洲欧美成人| 亚洲自拍欧美另类| 91欧美激情另类亚洲| 一区二区福利视频| 欧美特黄级在线| 亚洲精品456在线播放狼人| 91chinesevideo永久地址| 国产午夜精品美女视频明星a级| 在线亚洲男人天堂| 亚洲影院色无极综合| 日韩中文字幕亚洲| 欧美有码在线视频| 粗暴蹂躏中文一区二区三区| 欧美亚洲另类激情另类| 欧美激情在线观看视频| 亚洲乱码av中文一区二区| 国内精品视频在线| 国产精品视频免费在线观看| 国产精品午夜一区二区欲梦| 2019中文字幕免费视频| 日韩国产高清视频在线| 91精品国产高清久久久久久久久| 精品二区三区线观看| 国产一区私人高清影院| 国产精品一区二区三区免费视频| 国产成人午夜视频网址| 亚洲欧洲一区二区三区久久| 国产精品99蜜臀久久不卡二区| 亚洲人免费视频| 国产a级全部精品| 久久久久久久久电影| 日本久久久久亚洲中字幕| 91精品在线看| 最近2019年日本中文免费字幕| 日韩电影在线观看永久视频免费网站| 91日本视频在线| 人人澡人人澡人人看欧美| 国产精品久久久久久超碰| 国产亚洲人成a一在线v站| 欧美日韩在线视频一区二区| 国产精品久久久久高潮| 亚洲第一网站免费视频| 国产精品亚洲自拍| 在线精品91av| yellow中文字幕久久| 久久国产精品亚洲| 一区二区三区精品99久久| 精品国产拍在线观看| 在线观看不卡av| 亚洲综合中文字幕68页| 欧美激情精品久久久久久大尺度| 国产香蕉精品视频一区二区三区| 欧美夫妻性视频| 国产美女精品视频免费观看| 欧美在线影院在线视频| 亚洲午夜国产成人av电影男同| 欧美日韩国产精品一区二区不卡中文| 亚洲一区二区三区久久| 欧美美最猛性xxxxxx| 亚洲电影中文字幕| 色综合伊人色综合网站| 色综久久综合桃花网| 久热爱精品视频线路一| 欧美精品在线播放| 久久久久久久久久久网站| 日韩av快播网址| 深夜成人在线观看| 中文字幕九色91在线| 欧美黑人狂野猛交老妇| 亚洲精品视频播放| 精品国产成人在线| 97精品国产91久久久久久| 深夜福利一区二区| 久久全国免费视频| 久久五月天色综合| 亚洲一区二区三区四区在线播放| 国产97色在线| 亚洲精品视频网上网址在线观看| 欧美激情亚洲国产| 日本国产高清不卡| 色悠悠久久88| 韩国精品久久久999| 亚洲第一国产精品| 欧美成人黄色小视频| 日韩高清欧美高清| 欧美中在线观看| 中文国产成人精品久久一| 欧美日韩不卡合集视频| 精品久久久久久久久中文字幕| 一区二区三区 在线观看视| 亚洲欧洲国产伦综合| 色偷偷偷综合中文字幕;dd| 亚洲综合在线播放| 国产精品永久在线| 精品美女国产在线| 欧美成人国产va精品日本一级| 国产91免费观看| 日本一区二区三区在线播放| 亚洲福利视频专区| 色偷偷av亚洲男人的天堂| 日韩视频欧美视频| 欧美成人剧情片在线观看| 日韩视频在线免费观看| 亚洲欧美一区二区三区在线| 日韩成人av在线播放| 中文字幕国产亚洲| 国产一区二区av| 欧美大码xxxx| 国产精品久久久久影院日本| 毛片精品免费在线观看| 中文字幕欧美在线| 这里只有精品丝袜| 欧美日韩在线免费| 久久免费高清视频| 日韩人体视频一二区|