1. 程式人生 > >Dubbo原始碼實現一:切入Spring

Dubbo原始碼實現一:切入Spring

        Dubbo是阿里開源的一個高效能服務框架,提供了服務註冊、RPC服務呼叫、呼叫均衡、服務監控和服務failover等功能。如果你還未使用過Dubbo框架,請先參考dubbo提供的官方文件,比如:http://www.oschina.net/p/dubbo?fromerr=iVZFqWON。

        Dubbo框架中有兩個重要角色:(服務)提供者和(服務)消費者,這裡為了簡單起見,將包含了dubbo提供者或消費者功能的應用模組通稱為dubbo客戶端

        帶著問題看原始碼,才能有收穫。

        進入正題,現在大多數java應用都離不開Spring,所以其他java解決方案,或多或少都會支援在Spring中使用,dubbo也不例外。在我記憶中,凡是想在Spring容器中發揮作用的框架,無非都是提供對應的Spring Bean來注入到Spring容器中,dubbo也一樣。在原始碼的dubbo-container-spring模組中,唯一的類SpringContainer說明了這一點,它的start()方法直接通過ClassPathXmlApplicationContext來啟動Spring容器。有人立馬會問,SpringContainer的start()方法由誰呼叫?答案就是com.alibaba.dubbo.container.Main,它是dubbo的入口,Main類中的main方法將依次呼叫dubbo內建的Container的start()方法。如果沒有配置Spring xml檔案的路徑,dubbo將會預設採用classpath*:META-INF/spring/*.xml。

         那麼問題來了,Spring是如何識別dubbo的那些自定義標籤的?Spring為了支援使用者自定義類載入到Spring容器,提供了org.springframework.beans.factory.xml.NamespaceHandler介面和org.springframework.beans.factory.xml.NamespaceHandlerSupport抽象類,NamespaceHandler#init方法會在物件的建構函式呼叫之後、屬性初始化之前被DefaultNamespaceHandlerResolver呼叫。dubbo的DubboNamespaceHandler類正是繼承了NamespaceHandlerSupport,其程式碼實現如下:

public class DubboNamespaceHandler extends NamespaceHandlerSupport {

	static {
		Version.checkDuplicate(DubboNamespaceHandler.class);
	}

	public void init() {
	    registerBeanDefinitionParser("application", new DubboBeanDefinitionParser(ApplicationConfig.class, true));
        registerBeanDefinitionParser("module", new DubboBeanDefinitionParser(ModuleConfig.class, true));
        registerBeanDefinitionParser("registry", new DubboBeanDefinitionParser(RegistryConfig.class, true));
        registerBeanDefinitionParser("monitor", new DubboBeanDefinitionParser(MonitorConfig.class, true));
        registerBeanDefinitionParser("provider", new DubboBeanDefinitionParser(ProviderConfig.class, true));
        registerBeanDefinitionParser("consumer", new DubboBeanDefinitionParser(ConsumerConfig.class, true));
        registerBeanDefinitionParser("protocol", new DubboBeanDefinitionParser(ProtocolConfig.class, true));
        registerBeanDefinitionParser("service", new DubboBeanDefinitionParser(ServiceBean.class, true));
        registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false));
        registerBeanDefinitionParser("annotation", new DubboBeanDefinitionParser(AnnotationBean.class, true));
    }

}

        registerBeanDefinitionParser方法有父抽象了類NamespaceHandlerSupport的預設實現,第一個引數是elementName,即元素名稱,即告訴Spring你要解析哪個標籤,第二個引數是BeanDefinitionParser的實現類,BeanDefinitionParser是Spring用來將xml元素轉換成BeanDefinition物件的介面。dubbo的DubboBeanDefinitionParser類就實現了這個介面,負責將標籤轉換成bean定義物件BeanDefinition。dubbo給其返回的BeanDefinition設定了下列屬性:

        beanDefinition.setBeanClass(beanClass);
        beanDefinition.setLazyInit(false);

        beanDefinition.getPropertyValues().addPropertyValue("id", id);

        如果是dubbo:protocol標籤,dubboh還會檢查所有已經包含protocol屬性的BeanDefinition且protocol屬性對應的值是ProtocolConfig物件的bean,將其屬性的protocol值設定成當前的bean引用:

        definition.getPropertyValues().addPropertyValue("protocol", new RuntimeBeanReference(id));

        如果是dubbo服務提供者的dubbo:service標籤,則還會設定ref屬性為對應介面class的實現類bean:

        beanDefinition.getPropertyValues().addPropertyValue("ref", new BeanDefinitionHolder(classDefinition, id + "Impl"));

        有沒有人想過,當使用dubbo服務提供者的dubbo:service標籤時,如果我既不設定id,也不設定name,則dubbo給它的ServiceBean在Spring容器中定義的ID是什麼? 答案就是:

            if (generatedBeanName == null || generatedBeanName.length() == 0) {
                generatedBeanName = beanClass.getName();
            }
            id = generatedBeanName;
            int counter = 2;
            while(parserContext.getRegistry().containsBeanDefinition(id)) {
                id = generatedBeanName + (counter ++);
            }

        有人就會問,Spring怎麼知道你自定義了NamespaceHandlerSupport的實現類?Spring容器會預設載入classpath/META-INF下的spring.handlers和spring.schemas檔案,來載入名空間處理器和xsd,所以dubbo-config-spring包下的META-INF目錄下就有這兩個檔案。

        最後,DubboNamespaceHandler類中的靜態程式碼塊去classpath下檢查是否有其他的同名class,否則會打錯誤日誌,這個是為什麼呢?防止不同的類載入器重複載入DubboNamespaceHandler?不得而知。

相關推薦

Dubbo原始碼實現切入Spring

        Dubbo是阿里開源的一個高效能服務框架,提供了服務註冊、RPC服務呼叫、呼叫均衡、服務監控和服務failover等功能。如果你還未使用過Dubbo框架,請先參考dubbo提供的官方文件,比如:http://www.oschina.net/p/dubbo?fromerr=iVZFqWON。

Dubbo原始碼實現Dubbo中的擴充套件點與SPI

       SPI的全稱是ServiceProviderInterface,即服務提供商介面。直白的說,它主要用來實現一個可擴充套件的Java應用。有人會覺得這就是建立在面向介面程式設計下的一種為了使元件可擴充套件或動態變更實現的規範,常見的類SPI的設計有JDBC、JN

Dubbo原始碼實現RPC中的服務消費方實現

        剛開始使用Dubbo的人,可能對Dubbo的第一印象就是它是一個RPC框架,當然,所有的分散式框架都少不了相互通訊的過程,何況Dubbo的任務就是幫助分散式業務系統完成服務的通訊、負載、註冊、發現和監控等功能。不得不承認,RPC是Dubbo提供服務的核心流程,

Dubbo原始碼分析()Dubbo原始碼的結構概述

1.dubbo原始碼的結構 Dubbo原始檔主要包含以上這麼多包,其中:        dubbo-common 公共邏輯模組,包括Util類和通用模型。        dubbo-remotin

Dubbo原始碼實現註冊中心Registry

        我們知道,對於服務治理框架來說,服務通訊(RPC)和服務管理兩部分必不可少,而服務管理又分為服務註冊、服務發現和服務人工介入,我們來看看Dubbo框架的結構圖(來源網路):   圖中可以看出,服務提供者Provider往服務註冊中心Registry註冊服務,

Dubbo原始碼實現服務呼叫的動態代理和負載均衡

疑惑一:為什麼在Spring中我們能像注入普通本地服務JavaBean一樣注入遠端的Dubbo服務Bean? 我們知道,Dubbo將服務呼叫封裝成普通的Spring的Bean,於是我們可以像使用本地的Spring Bean一樣,來呼叫遠端的Dubbo服務,並有LoadBal

JAVA中的集合原始碼分析ArrayList的內部實現原理

作為以java為語言開發的android開發者,集合幾乎天天都要打交道,無論是使用頻率最高的ArrayList還是HashSet,都頻繁的出現在平時的工作中。但是其中的原理之前卻一直沒深入探究,接下來記錄一下這次自己學習ArrayList原始碼的過程。 一.構造方法:

Spring boot 學習 認識Spring boot

XML 過程 maven 認識 很多 團隊 但是 日誌文件 pivotal 什麽是spring boot Spring Boot是由Pivotal團隊提供的全新框架,其設計目的是用來簡化新Spring應用的初始搭建以及開發過程。該框架使用了特定的方式來進行配置,從而使開發人

springcloud()大話Spring Cloud

servlet 基礎 抽象 三方庫 公司 for 全面 cluster DApp 研究了一段時間Spring Boot了準備向Spring Cloud進發,公司架構和項目也全面擁抱了Spring Cloud。在使用了一段時間後發現Spring Cloud從技術架構上降低了對

Elastic-Job原始碼解析()之與Spring完美整合

看過小編寫SpringFramework原始碼解析的同學應該對Spring支援自定義標籤還有點印象吧,沒有的話我們回顧下,然後看看Elastic-Job是如何巧妙的利用自定義標籤生成Job任務的吧。請注意這裡用了一個巧妙關鍵字。我們看它如何巧妙的吧。 Spring自定義

IM訊息送達保證機制實現()保證線上實時訊息的可靠投遞

1、前言 網際網路發展至今,IM(即時通訊聊天應用)一直是網際網路上最為成功也是最為平常的應用型別。尤其現今的移動網際網路時代,因即時通訊技術的發展和普及,IM這種即時通訊應用已乎達成了各即時通訊應用運營者夢寐已求的所謂“全時線上”,而這種“全時線上”及其應用體驗的背後,迴歸到技術本質就是各種

【視訊】超級賬本HyperLedgerFabric原始碼走讀()專案構建與程式碼結構

作者: 李佶澳   轉載請保留:原文地址   釋出時間:2018/11/18 14:26:00   說明 編譯方法 make peer make release 和 make r

Spring Security教程()初識Spring Security

一、概要 Spring Security,這是一種基於 Spring AOP 和 Servlet 過濾器的安全框架。它提供全面的安全性解決方案,同時在 Web 請求級和方法呼叫級處理身份確認和授權。以下是百科裡對於Spring Security的介紹。 Spring Security是一個能夠為基於Spr

從資料流角度管窺 Moya 的實現()構建請求

相信大家都封裝過網路層。 雖然系統提供的網路庫以及一些著名的第三方網路庫(AFNetworking, Alamofire)已經能滿足各種 HTTP/HTTPS的網路請求,但直接在程式碼裡用起來,終歸是比較晦澀,不是那麼的順手。所以我們都會傾向於根據自己的實際需求,再封裝

Glide 原始碼分析()圖片壓縮

關於圖片的那點事兒 Q: 一張大小為 55KB, 解析度為 1080 * 480 的 PNG 圖片,它載入近記憶體時所佔的大小是多少呢? 圖片記憶體大小 圖片佔用記憶體大小 = 解析度 * 畫素點大小 其中資料格式不同畫素點大小也不同: ALPHA_8: 1B RGB_565: 2B

Alamofire原始碼導讀框架

原始碼架構  Alamofire 的原始碼包括 Core、Extensions、Features、Supporting Files。其中主要邏輯在 Core裡。 包括構造請求,發起請求,處理回撥等。 Core 的架構  Core 中主要有 SessionManager、SessionDeleg

jdk1.8原始碼解析Object類

  Object 類屬於 java.lang 包,此包下的所有類在使用時無需手動匯入,系統會在程式編譯期間自動匯入。Object 類是所有類的基類,當一個類沒有直接繼承某個類時,預設繼承Object類,也就是說任何類都直接或間接繼承此類,Object 類中能訪問的方法在所有類

dubbo原始碼分析()-從xml到我們認識的Java物件

  專案中用的dubbo的挺多的,然後隨著自己對dubbo的慢慢深入,自己也希望能夠了解dubbo的底層實現,這半年來一直在看dubbo的原始碼,有點斷斷續續的,於是準備寫一個dubbo原始碼系列的分析文章,一來方便自己總結,二來也能夠讓自己的學習有輸出分享。  整個系列會從dubbo的xml到bean到生

挺過最艱難的2018,我終將長大 沉澱年,我想推薦這些書給你 dubbo原始碼分析()-從xml到我們認識的Java物件

    2017年結束之後一直沒有更新部落格,2017年的年終總結也沒有寫,一直覺的自己欠自己一個2017。這一年沒有繼續寫部落格,一個原因是自己一整年在瞎忙,忙的暈頭轉向且感覺也沒有收穫多少,同事家裡也發生變故;二是感覺個人沉澱的不夠,需要靜下心沉澱技術與人生。終於渾渾噩噩的2018的過去了,要迎來嶄新的2

通用資料級許可權控制解決方案的實現()Cube中的自定義DLL

BI資料分析是目前企業的熱門應用,而對企業來說,進行許可權控制是必須而且非常重要的,尤其是作為決策用的企業報表。在BI解決方案中,許可權控制又分為2種:一種是報表級許可權控制,這型別許可權控制沒有什麼好講的,報表系統都本身就支援了。另一種比較複雜的就是資料級許可權控制,所