dubbo中Listener的實現

来源:http://www.cnblogs.com/killbug/archive/2017/08/10/7341968.html
-Advertisement-
Play Games

這裡繼續dubbo的源碼旅程,在過程中學習它的設計和技巧,看優秀的代碼,我想對我們日程編碼必然有幫助的。而那些開源的代碼正是千錘百煉的東西,希望和各位共勉。 拿ProtocolListenerWrapper為例子,看源碼的時候發現它是一個裝飾類的標準實現有一個自身的複製構造函數,把被包裝者複製進來, ...


這裡繼續dubbo的源碼旅程,在過程中學習它的設計和技巧,看優秀的代碼,我想對我們日程編碼必然有幫助的。而那些開源的代碼正是千錘百煉的東西,希望和各位共勉。

拿ProtocolListenerWrapper為例子,看源碼的時候發現它是一個裝飾類的標準實現有一個自身的複製構造函數,把被包裝者複製進來,然後結合裝飾部分的操作。看下ProtocolListenerWrapper類有這樣的代碼:

public class ProtocolListenerWrapper implements Protocol {

    private final Protocol protocol;

    public ProtocolListenerWrapper(Protocol protocol){
        if (protocol == null) {
            throw new IllegalArgumentException("protocol == null");
        }
        this.protocol = protocol;
    }

    public int getDefaultPort() {
        return protocol.getDefaultPort();
    }

    public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
        if (Constants.REGISTRY_PROTOCOL.equals(invoker.getUrl().getProtocol())) {
            return protocol.export(invoker);
        }
        return new ListenerExporterWrapper<T>(protocol.export(invoker),
                Collections.unmodifiableList(ExtensionLoader.getExtensionLoader(ExporterListener.class)
                        .getActivateExtension(invoker.getUrl(), Constants.EXPORTER_LISTENER_KEY)));
    }

    public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
        if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
            return protocol.refer(type, url);
        }
        return new ListenerInvokerWrapper<T>(protocol.refer(type, url),
                Collections.unmodifiableList(
                        ExtensionLoader.getExtensionLoader(InvokerListener.class)
                        .getActivateExtension(url, Constants.INVOKER_LISTENER_KEY)));
    }

    public void destroy() {
        protocol.destroy();
    }

}
而我們在ExtensionLoader里找到了這份代碼片段clazz.getConstructor()方法就是去匹配前面提到的裝飾模式用到的方式。 而這些類作為插件會被放入cachedWrapperClasses進行緩存。而對這個緩存的使用就是解開listenter調用實現的鑰匙。
try {
    clazz.getConstructor(type);
    Set<Class<?>> wrappers = cachedWrapperClasses;
    if (wrappers == null) {
        cachedWrapperClasses = new ConcurrentHashSet<Class<?>>();
        wrappers = cachedWrapperClasses;
    }
    wrappers.add(clazz);
} catch (NoSuchMethodException e) {

上面也可以看到用一場作為一個判斷邏輯。

ExtensionLoader中getExtension(String name)方法中會調用createExtension(String name)這個方法中將cachedWrapperClasses利用了起來,具體實現就是將被裝飾類實例作為參數調用warpper類的自身複製構造函數,這樣就會把被裝飾累包裝起來,從而達到,當有調用被裝飾類的方法是就可以執行到warpper中的邏輯代碼了,實現都是調用了clazz.getConstructor方法,代碼片段:

Set<Class<?>> wrapperClasses = cachedWrapperClasses;
if (wrapperClasses != null && wrapperClasses.size() > 0) {
    for (Class<?> wrapperClass : wrapperClasses) {
        instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
    }
}
再回去看一下ProtocolListenerWrapper,我們可以發現繼承Protocol中的export方法是對外開放service的入口方法,它返回exporter,代碼中實際是返回了ListenerExporterWrapper,這也是個裝飾類,不過沒有使用上面提到的機制,只是把exporter和listener進行類包裝,在構造函數里將listener執行。至此我們終於找到了執行listener的代碼。 在dubbo的開發中listener是及其重要的一個擴展口子,在服務對外時執行一些自己想做的事情就些各類繼承ExporterListener 在引用服務的時候想做些自己的事就寫個類繼承InvokerListener。   另外,ExporterListener為例,發現他的子類中有一個ExporterListenerAdapter,兩個空方法,代碼:
public abstract class ExporterListenerAdapter implements ExporterListener {

    public void exported(Exporter<?> exporter) throws RpcException {
    }

    public void unexported(Exporter<?> exporter) throws RpcException {
    }

}

這是個技巧吧,剛剛上面提到自己要寫擴展類的時候就不直接繼承ExporterListener了,因為直接繼承介面會強制要求實現兩個方法的,而實際編碼中dubbo的作者應該也發現這兩個方法是完全不同的業務時使用,所有我們可以只繼承ExporterListenerAdapter,如此自己的業務代碼中就不需要出現一個空方法了。

 
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前幾天公司來了個新同事,使用的VS2013,但我們的所有項目都是使用VS2012創建的,我想用13打開應該沒有什麼問題。昨天新同事修改完代碼提交後,我獲取完成後無法編譯成功,提示: 錯誤 3 命令“mkdir "E:\vssdata\BCenter.root\BCenter\BCenter.Cont ...
  • 最近需要把用戶的一些行為添加到資料庫中,所以想到了用log4net ,如果有別的好的方案,大家可以給我指正。 先看一下配置文件 我這個是控制台文件 app.config MyLayout 是一個映射類 控制台文 因為項目和別的項目相連,所以有需要的需要引用現有項目就可以 下載鏈接:http://pa ...
  • 本快速入門幫助你在數分鐘內將你的第一個 ASP.NET Web 應用部署到 Azure 應用服務。完成本教程後,你將能夠在雲中啟動並運行一個簡單的 Web 應用。在本教程中完成的所有操作均符合 1 元試用條件。 開始之前 本教程演示如何使用 Visual Studio 2017 構建 ASP.NET ...
  • 一、前言 最近公司新項目,需要搭架構進行開發,其中需要對一些日誌進行輸出,經過一番查找,發現很多博文都是通過Spring.Net、Unity、PostSharp、Castle Windsor這些方式實現AOP的。但是這不是我想要的,因此一番查找後,使用 該方式實現AOP。 二、使用AOP的優勢 博主 ...
  • 認識許可權 UGO Linux系統中許可權是基於UGO模型進行控制的。 實踐: 修改文件所屬用戶,組 實踐:創建目錄linuxcast.net,然後修改該目錄的所屬用戶和組。 創建文件和目錄的時候,預設是屬於當前登錄用戶和所屬組 修改許可權 實踐:如果要使linuxcast.net只能被用戶luning和 ...
  • 一、演算法原理 比較相鄰的元素。如果第一個比第二個大,就交換他們兩個。 對每一對相鄰元素作同樣的工作,從開始第一對到結尾的最後一對。在這一點,最後的元素應該會是最大的數。 針對所有的元素重覆以上的步驟,除了最後一個。 持續每次對越來越少的元素重覆上面的步驟,直到沒有任何一對數字需要比較。 二、實現思路 ...
  • 一 python第一個程式 二 變數 2.1 變數名稱規則 變數名只能是 字母、數字或下劃線的任意組合 變數名的第一個字元不能是數字 以下關鍵字不能聲明為變數名 ['and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', ' ...
  • 特殊字元 . 通配符 \ 轉義字元 [ ] 字元集 ( | ) 選擇字元 ? * + 重覆 (?一次或沒有,* 零次或多次 >=0, + 一次或多次 >=1) ^ 以什麼開頭 $ 以什麼結尾 re模塊中操作正則表達式的函數 pat = re.compile(pattern) 將正則表達式轉換為模式對 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...