中文字幕在线观看,亚洲а∨天堂久久精品9966,亚洲成a人片在线观看你懂的,亚洲av成人片无码网站,亚洲国产精品无码久久久五月天

Java 動(dòng)態(tài)代理及 RPC 框架介紹

2018-08-01    來(lái)源:importnew

容器云強(qiáng)勢(shì)上線!快速搭建集群,上萬(wàn)Linux鏡像隨意使用

所謂動(dòng)態(tài)代理,指的是語(yǔ)言提供的一種語(yǔ)法,能夠?qū)?duì)對(duì)象中不同方法的調(diào)用重定向到一個(gè)統(tǒng)一的處理函數(shù)中來(lái)。
python重寫__getattr__函數(shù)能夠做到這一點(diǎn),就連世界上最好的語(yǔ)言也提供稱為魔術(shù)方法的__call
這種語(yǔ)法除了能更好的實(shí)現(xiàn)動(dòng)態(tài)代理外,還是RPC框架實(shí)現(xiàn)原理的一部分。

1. 動(dòng)態(tài)代理是什么

動(dòng)態(tài)代理提供一種抽象,能夠?qū)?duì)象中不同方法的調(diào)用重定向到一個(gè)統(tǒng)一的處理函數(shù),做自定義的邏輯處理。
但是對(duì)于調(diào)用者,對(duì)此毫無(wú)察覺(jué),就好像調(diào)用的方法是用傳統(tǒng)方式實(shí)現(xiàn)的一般。

這種語(yǔ)法,在java中被稱為動(dòng)態(tài)代理。之所以叫做動(dòng)態(tài)代理,是因?yàn)樗鼙苊鈧鹘y(tǒng)代理模式實(shí)現(xiàn)中人工一個(gè)一個(gè)的將java函數(shù)轉(zhuǎn)發(fā)過(guò)去,
而是能夠讓代碼自動(dòng)做到這一點(diǎn),這樣代理類的代碼是和業(yè)務(wù)無(wú)關(guān)的,不會(huì)因?yàn)闃I(yè)務(wù)類的方法增多而逐漸龐大。
使代碼更易維護(hù)更易修改,實(shí)現(xiàn)自動(dòng)化搬磚。

實(shí)際上,被代理的類不一定位于本機(jī)類,動(dòng)態(tài)代理語(yǔ)法提供了一種抽象方式,被代理的類也可以位于遠(yuǎn)程主機(jī)上,這也是RPC框架實(shí)現(xiàn)原理的一部分。

理解了動(dòng)態(tài)代理的概念后不難發(fā)現(xiàn),動(dòng)態(tài)代理概念上有著這么幾個(gè)部分:

  1. 給調(diào)用者使用的代理類。在java中,我們發(fā)現(xiàn)動(dòng)態(tài)代理提供的抽象天然契合面向接口編程,因此它也有可能是接口。
  2. 一個(gè)統(tǒng)一的處理函數(shù),收集不同函數(shù)轉(zhuǎn)發(fā)過(guò)來(lái)的請(qǐng)求,可自定義處理邏輯集中處理。java中它可能會(huì)成為一個(gè)較獨(dú)立的部分,因此也可能是類。

2. java動(dòng)態(tài)代理機(jī)制

理解了概念,就不難理解java動(dòng)態(tài)代理的機(jī)制了。下面來(lái)看看java動(dòng)態(tài)代理機(jī)制如何代理一個(gè)本地對(duì)象。

2.1. 代理接口

首先看第一個(gè)部分,給調(diào)用者使用的代理類。在java動(dòng)態(tài)代理機(jī)制中,這個(gè)角色只能是接口。我們定義一個(gè)整數(shù)運(yùn)算接口:

interface NumberOperationInterface {
    int add(int a, int b);
}

2.2. 代理處理器

再看第二個(gè)角色,統(tǒng)一的處理函數(shù)。在java中它的確是類,通過(guò)實(shí)現(xiàn)InvocationHandler接口定義。

class NumberOperationImpProxyHandler implements InvocationHandler {
    private Object proxied;
    public RealObjectProxyHandler(Object proxied) {
        this.proxied = proxied;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.printf("調(diào)用函數(shù)%s\n", method.getName());
        return method.invoke(proxied, args);
    }
}
  1. 由于我們的例子是代理本地對(duì)象,那么處理函數(shù)是需要被代理對(duì)象的信息。可以看到,我們從構(gòu)造函數(shù)中將被代理對(duì)象保存在該類中,即可從處理函數(shù)中訪問(wèn)到。
  2. invoke函數(shù)中,對(duì)代理對(duì)象的所有方法的調(diào)用都被轉(zhuǎn)發(fā)至該函數(shù)處理。在這里可以靈活的自定義各種你能想到的邏輯。在上面的代碼中,我們使用反射調(diào)用被代理對(duì)象的同名方法實(shí)現(xiàn)。

2.3. 被代理類

由于我們的示例是代理本地對(duì)象,因此還需要一個(gè)被代理對(duì)象的類:

class NumberOperationImp implements NumerOperationInterface {
    @Override
    public int add(int a, int b) {
        return a + b;
    }
}

2.4. 創(chuàng)建代理對(duì)象

好了,各個(gè)組成部分都定義完成。現(xiàn)在把它們組合起來(lái):

public NumerOperationInterface wrap(NumerOperationInterface proxied) {
    return (NumerOperationInterface) Proxy.newProxyInstance(
        NumerOperationInterface.class.getClassLoader(),
        new Class[]{NumerOperationInterface.class},
        new NumberOperationImpProxyHandler(proxied));
}
  1. 由于java提供的這個(gè)寫法實(shí)在是太啰嗦了,所以把它放入一個(gè)輔助函數(shù)中。
  2. Proxy.newProxyInstance?方法能夠根據(jù)提供的接口和代理處理器創(chuàng)建代理對(duì)象。

java提供的寫法太啰嗦了,可以考慮使用Guake提供的輔助函數(shù)簡(jiǎn)化下代碼。如下:

public NumerOperationInterface wrap(NumerOperationInterface proxied) {
    return Reflection.newProxy(NumerOperationInterface.class, new NumberOperationImpProxyHandler(proxied));
}

好了,現(xiàn)在調(diào)用下試試:

NumerOperationInterface proxied = new NumberOperationImp();
real = wrap(proxied);
real.add(1, 2);

2.5. 總結(jié)

動(dòng)態(tài)代理聽(tīng)起來(lái)是代理模式的動(dòng)態(tài)實(shí)現(xiàn),可是結(jié)合上面的最終效果,不覺(jué)得這個(gè)叫做動(dòng)態(tài)裝飾器更合適嗎?

3. 動(dòng)態(tài)代理的應(yīng)用

說(shuō)完了動(dòng)態(tài)代理的概念和實(shí)現(xiàn)機(jī)制,該看看使用動(dòng)態(tài)代理有哪些應(yīng)用。

3.1. 應(yīng)用一:代理模式/裝飾器模式的動(dòng)態(tài)實(shí)現(xiàn)

這個(gè)應(yīng)用場(chǎng)景前面據(jù)已經(jīng)提到過(guò)。
代理模式和裝飾器模式是編程當(dāng)中很常用的技巧,用于提升代碼的靈活性和可擴(kuò)展性。
傳統(tǒng)代理模式的實(shí)現(xiàn)方式比較暴力直接,需要將所有被代理類的所有方法都寫一遍,并且一個(gè)個(gè)的手動(dòng)轉(zhuǎn)發(fā)過(guò)去。
在維護(hù)被代理類的同時(shí),作為java碼工還需要同時(shí)維護(hù)代理類的相關(guān)代碼,實(shí)在是累心。

通過(guò)使用動(dòng)態(tài)代理,動(dòng)態(tài)代理能夠自動(dòng)將代理類的相關(guān)方法轉(zhuǎn)發(fā)到被代理類,可以看到:

  1. 代理轉(zhuǎn)發(fā)的過(guò)程自動(dòng)化了,實(shí)現(xiàn)自動(dòng)化搬磚。
  2. 代理類的代碼邏輯和具體業(yè)務(wù)邏輯解耦,與業(yè)務(wù)無(wú)關(guān)。

3.2. 應(yīng)用二:實(shí)現(xiàn)AOP

是的,利用動(dòng)態(tài)代理也能實(shí)現(xiàn)AOP。仔細(xì)推演一下不能得出這個(gè)結(jié)論。我們知道:

  1. 動(dòng)態(tài)代理提供了一種方式,能夠?qū)⒎稚⒌姆椒ㄕ{(diào)用轉(zhuǎn)發(fā)到一個(gè)統(tǒng)一的處理函數(shù)處理。
  2. AOP的實(shí)現(xiàn)需要能夠提供這樣一種機(jī)制,即在執(zhí)行函數(shù)前和執(zhí)行函數(shù)后都能執(zhí)行自己定義的鉤子。

那么,首先使用動(dòng)態(tài)代理讓代理類忠實(shí)的代理被代理類,然后處理函數(shù)中插入我們的自定義的鉤子。
之后讓代理類替換被代理類需要使用的場(chǎng)景,這樣,相當(dāng)于對(duì)該類的所有方法定義了一個(gè)切面。

不過(guò),使用動(dòng)態(tài)代理實(shí)現(xiàn)AOP特別麻煩,啰嗦。這僅僅作為一個(gè)探討的思路,來(lái)說(shuō)明動(dòng)態(tài)代理這一通用概念可以實(shí)現(xiàn)很多特定技術(shù)。
實(shí)際使用中當(dāng)然使用spring提供的AOP更為方便。

3.3. 應(yīng)用三:實(shí)現(xiàn)RPC

RPC即遠(yuǎn)程過(guò)程調(diào)用,在分布式的網(wǎng)站架構(gòu)中是一個(gè)非常重要的技術(shù),目前現(xiàn)在流行的SOA架構(gòu),微服務(wù)架構(gòu),它們的核心原理之一就是RPC調(diào)用。

從概念上來(lái)說(shuō),RPC的概念是非常簡(jiǎn)潔優(yōu)美的。RPC方法的調(diào)用和普通的方法并無(wú)二異,調(diào)用者不需要操心具體的實(shí)現(xiàn),這是抽象提供的威力。
實(shí)現(xiàn)上,它將函數(shù)調(diào)用方和函數(shù)的提供方分散在兩個(gè)不同的進(jìn)程上,中間使用網(wǎng)絡(luò)通信來(lái)進(jìn)行數(shù)據(jù)交互。

動(dòng)態(tài)代理就是實(shí)現(xiàn)RPC的技術(shù)之一。只要理解了動(dòng)態(tài)代理和RPC,我們很容易發(fā)現(xiàn)這樣一個(gè)事實(shí):
RPC調(diào)用其實(shí)是對(duì)遠(yuǎn)程另外一臺(tái)機(jī)器進(jìn)程上的對(duì)象的代理。

仔細(xì)思考RPC調(diào)用的數(shù)據(jù)流流向,就能梳理出這樣的思路:

  1. 調(diào)用方調(diào)用本地的RPC代理方法,將參數(shù)提供給該方法。
  2. 不同的RPC代理方法被轉(zhuǎn)發(fā)到一個(gè)統(tǒng)一的處理中心,該處理中心知道調(diào)用的是那個(gè)函數(shù),參數(shù)是什么。
  3. 該處理中心將調(diào)用的信息封裝打包,通過(guò)網(wǎng)絡(luò)發(fā)送給另外一個(gè)進(jìn)程。
  4. 另外一個(gè)進(jìn)程接受到調(diào)用進(jìn)程發(fā)送過(guò)來(lái)的數(shù)據(jù)包。
  5. 該進(jìn)程根據(jù)數(shù)據(jù)包中記錄的RPC調(diào)用信息,將調(diào)用分發(fā)給對(duì)應(yīng)的被代理對(duì)象的對(duì)應(yīng)方法去執(zhí)行。
  6. 返回的話思路類似。

顯而易見(jiàn),第二步,需要使用動(dòng)態(tài)代理將分散的函數(shù)調(diào)用轉(zhuǎn)發(fā)到一個(gè)統(tǒng)一的處理中心;第五步,將統(tǒng)一收集來(lái)的調(diào)用信息分發(fā)給具體的函數(shù)執(zhí)行,顯然使用反射做到這一點(diǎn)。
有了這個(gè)思路,通過(guò)利用動(dòng)態(tài)代理,反射,和網(wǎng)絡(luò)編程技術(shù),實(shí)現(xiàn)一個(gè)簡(jiǎn)易版的RPC框架也就不難了。
考慮到本文是介紹動(dòng)態(tài)代理的,關(guān)于RPC的細(xì)節(jié)實(shí)現(xiàn)有時(shí)間新開(kāi)一篇博文分析。

4. 最后

總得來(lái)說(shuō),通過(guò)一定的思考,個(gè)人覺(jué)得動(dòng)態(tài)代理的核心在于:將分散的對(duì)對(duì)象不同方法的調(diào)用轉(zhuǎn)發(fā)到一個(gè)同一的處理函數(shù)中來(lái)。

有了這個(gè)關(guān)鍵點(diǎn),很多其它技術(shù)的實(shí)現(xiàn)需要借助于動(dòng)態(tài)代理的這一個(gè)關(guān)鍵點(diǎn)實(shí)現(xiàn),也因此動(dòng)態(tài)代理也有著這么多的應(yīng)用。

標(biāo)簽: ssl 代碼 通信 網(wǎng)絡(luò)

版權(quán)申明:本站文章部分自網(wǎng)絡(luò),如有侵權(quán),請(qǐng)聯(lián)系:west999com@outlook.com
特別注意:本站所有轉(zhuǎn)載文章言論不代表本站觀點(diǎn)!
本站所提供的圖片等素材,版權(quán)歸原作者所有,如需使用,請(qǐng)與原作者聯(lián)系。

上一篇:SpringBoot | 第四章 :日志管理

下一篇:SpringBoot | 第三章:springboot配置詳解