Dubbo篇:ServiceBean服務(wù)暴露源碼分析


ServiceBean概述



????????ServiceBean是Dubbo中很重要的一個類,每個暴露出去的服務(wù)都會生成一個ServiceBean,ServiceBean的繼承關(guān)系如下圖。

在這里插入圖片描述

????????ServiceBean繼承自ServiceConfig,ServiceConfig是服務(wù)暴露的具體實(shí)現(xiàn)類。另外ServiceBean還實(shí)現(xiàn)了InitializingBean,DisposableBean,ApplicationContextAware,ApplicationListener,BeanNameAware,
ApplicationEventPublisherAware幾個接口,簡單介紹下幾個接口的作用:

????????繼承InitializingBean實(shí)現(xiàn)其afterPropertiesSet方法,對象實(shí)例化完畢后,調(diào)用該方法。
????????繼承ApplicationListener接口,監(jiān)聽上下文監(jiān)聽事件contextrefreshedevent事件,當(dāng)Spring容器啟動完成后會發(fā)布該事件,監(jiān)聽到之后會執(zhí)行onApplicationEvent()方法。
????????繼承DisposableBean實(shí)現(xiàn)其destory()方法,在實(shí)例生命周期結(jié)束前,會調(diào)用該方法。
????????繼承BeanNameWare,用于設(shè)置Bean的名稱
????????繼承ApplicationContextAware,用于獲取Spring容器的上下文
????????繼承ApplicationEventPublisherAware接口,用于發(fā)布事件。





源碼分析



????????ServiceBean繼承了InitializingBean接口,所以,實(shí)例化之后就會調(diào)用其afterPropertiesSet()方法。afterPropertiesSet()方法實(shí)現(xiàn)有點(diǎn)長,就不展開描述了,其功能主要是對ProviderConfig、ApplicationConfig、ModuleConfig、RegistryConfig、MetadataConfig、ConfigCenter、MonitorConfig等配置Bean的處理,如果標(biāo)簽未配置,會從Spring容器中獲取這些配置,然后設(shè)置到當(dāng)前的ServiceBean中。最后會判斷當(dāng)前是否支持事件監(jiān)聽機(jī)制,如果不支持,就會在最后通過export()方法暴露Dubbo服務(wù)。

????????ServiceBean實(shí)現(xiàn)了ApplicationListener接口,當(dāng)ApplicationContext啟動完成事件后調(diào)用其onApplicationEvent()方法如下:

在這里插入圖片描述

????????此處會調(diào)用其父類的ServiceConfig的export方法完成服務(wù)暴露,代碼實(shí)現(xiàn)如下:

在這里插入圖片描述

????????此方法中主要做了檢查屬性的配置,并且根據(jù)配置的優(yōu)先級進(jìn)行屬性的覆蓋,初始化ServiceMetadata,檢查配置邏輯還是蠻長的,此處只關(guān)注服務(wù)暴露流程,就不展開介紹了,直接進(jìn)入doExport()方法:

在這里插入圖片描述

????????對所有配置的協(xié)議進(jìn)行服務(wù)暴露,此處只配置了一個dubbo協(xié)議,所以就只暴露dubbo,繼續(xù)跟進(jìn)到doExportUrlsFor1Protocol()方法進(jìn)行服務(wù)暴露,doExportUrlsFor1Protocol()方法實(shí)現(xiàn)也是非常之長,大部分篇幅用于屬性配置的處理工作,本文只關(guān)注服務(wù)暴露相關(guān),代碼如下:


在這里插入圖片描述

????????注釋出自Dubbo配置屬性初始化解析,感謝大佬詳細(xì)的注釋,才能讓初學(xué)者節(jié)省了大量的學(xué)習(xí)成本。

????????前部分主要通過反射獲取配置對象并放到map用于后續(xù)構(gòu)造URL參數(shù),然后以URL為基礎(chǔ)暴露服務(wù)。

????????服務(wù)暴露主要分為injvm和registry,即本地服務(wù)暴露和遠(yuǎn)程服務(wù)暴露,區(qū)別在于遠(yuǎn)程服務(wù)暴露還會將服務(wù)注冊信息registryURL等通過動態(tài)代理轉(zhuǎn)換成Invoker,使用export作為key追加服務(wù)元數(shù)據(jù)信息,遠(yuǎn)程服務(wù)暴露時也會根據(jù)相應(yīng)協(xié)議在本地進(jìn)行一次服務(wù)暴露,可以本地服務(wù)直連。

????????此方法主要做的是服務(wù)暴露的前置工作,其暴露邏輯主要位于RegitryProtocol#export方法,代碼實(shí)現(xiàn)如下:

在這里插入圖片描述

????????注釋出自大佬的另一篇文章Dubbo服務(wù)暴露與注冊,其主要功能是,首先委托具體協(xié)議(此處為Dubbo)進(jìn)行服務(wù)暴露,創(chuàng)建NettyServer(默認(rèn)為Netty)監(jiān)聽端口和保存服務(wù)實(shí)例,然后創(chuàng)建注冊中心對象,與注冊中心創(chuàng)建TCP鏈接,注冊服務(wù)元數(shù)據(jù)到注冊中心,訂閱configurators節(jié)點(diǎn),監(jiān)聽服務(wù)動態(tài)屬性變更事件,設(shè)置相關(guān)的URL對象,并且使用DestroyableExporter對exporter進(jìn)行封裝返回。

????????服務(wù)暴露調(diào)用了doLocalExport()方法,因?yàn)榇颂幾罱K使用dubbo協(xié)議進(jìn)行服務(wù)暴露,所以最終調(diào)用DubboProtocol#export方法,代碼如下:

在這里插入圖片描述

????????主要實(shí)現(xiàn)為根據(jù)服務(wù)分組、版本、服務(wù)接口和暴露端口作為key用于關(guān)聯(lián)具體服務(wù)Invoker,注冊stub事件分發(fā)器,服務(wù)初次暴露會創(chuàng)建監(jiān)聽服務(wù)器,此時會觸發(fā)HeaderExchanger中的綁定方法,最終調(diào)用NettyServer進(jìn)行處理,一個標(biāo)準(zhǔn)的Netty服務(wù)器啟動流程,詳細(xì)后續(xù)介紹。最后注冊序列化類。

????????至此,一個服務(wù)暴露流程基本介紹完畢。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容