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

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

2018-08-01    來源:importnew

容器云強勢上線!快速搭建集群,上萬Linux鏡像隨意使用

所謂動態(tài)代理,指的是語言提供的一種語法,能夠?qū)ο笾胁煌椒ǖ恼{(diào)用重定向到一個統(tǒng)一的處理函數(shù)中來。
python重寫__getattr__函數(shù)能夠做到這一點,就連世界上最好的語言也提供稱為魔術方法的__call。
這種語法除了能更好的實現(xiàn)動態(tài)代理外,還是RPC框架實現(xiàn)原理的一部分。

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

動態(tài)代理提供一種抽象,能夠?qū)ο笾胁煌椒ǖ恼{(diào)用重定向到一個統(tǒng)一的處理函數(shù),做自定義的邏輯處理。
但是對于調(diào)用者,對此毫無察覺,就好像調(diào)用的方法是用傳統(tǒng)方式實現(xiàn)的一般。

這種語法,在java中被稱為動態(tài)代理。之所以叫做動態(tài)代理,是因為它能避免傳統(tǒng)代理模式實現(xiàn)中人工一個一個的將java函數(shù)轉發(fā)過去,
而是能夠讓代碼自動做到這一點,這樣代理類的代碼是和業(yè)務無關的,不會因為業(yè)務類的方法增多而逐漸龐大。
使代碼更易維護更易修改,實現(xiàn)自動化搬磚。

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

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

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

2. java動態(tài)代理機制

理解了概念,就不難理解java動態(tài)代理的機制了。下面來看看java動態(tài)代理機制如何代理一個本地對象。

2.1. 代理接口

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

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

2.2. 代理處理器

再看第二個角色,統(tǒng)一的處理函數(shù)。在java中它的確是類,通過實現(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. 由于我們的例子是代理本地對象,那么處理函數(shù)是需要被代理對象的信息?梢钥吹,我們從構造函數(shù)中將被代理對象保存在該類中,即可從處理函數(shù)中訪問到。
  2. invoke函數(shù)中,對代理對象的所有方法的調(diào)用都被轉發(fā)至該函數(shù)處理。在這里可以靈活的自定義各種你能想到的邏輯。在上面的代碼中,我們使用反射調(diào)用被代理對象的同名方法實現(xiàn)。

2.3. 被代理類

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

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

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

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

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

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

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. 總結

動態(tài)代理聽起來是代理模式的動態(tài)實現(xiàn),可是結合上面的最終效果,不覺得這個叫做動態(tài)裝飾器更合適嗎?

3. 動態(tài)代理的應用

說完了動態(tài)代理的概念和實現(xiàn)機制,該看看使用動態(tài)代理有哪些應用。

3.1. 應用一:代理模式/裝飾器模式的動態(tài)實現(xiàn)

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

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

  1. 代理轉發(fā)的過程自動化了,實現(xiàn)自動化搬磚。
  2. 代理類的代碼邏輯和具體業(yè)務邏輯解耦,與業(yè)務無關。

3.2. 應用二:實現(xiàn)AOP

是的,利用動態(tài)代理也能實現(xiàn)AOP。仔細推演一下不能得出這個結論。我們知道:

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

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

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

3.3. 應用三:實現(xiàn)RPC

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

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

動態(tài)代理就是實現(xiàn)RPC的技術之一。只要理解了動態(tài)代理和RPC,我們很容易發(fā)現(xiàn)這樣一個事實:
RPC調(diào)用其實是對遠程另外一臺機器進程上的對象的代理。

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

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

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

4. 最后

總得來說,通過一定的思考,個人覺得動態(tài)代理的核心在于:將分散的對對象不同方法的調(diào)用轉發(fā)到一個同一的處理函數(shù)中來。

有了這個關鍵點,很多其它技術的實現(xiàn)需要借助于動態(tài)代理的這一個關鍵點實現(xiàn),也因此動態(tài)代理也有著這么多的應用。

標簽: ssl 代碼 通信 網(wǎng)絡

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

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

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