要了解服務(wù)導(dǎo)出做了什么,需要了解導(dǎo)出的目的是什么?
dubbo是一款面向接口代理的高性能RPC調(diào)用,說白了就是提供遠(yuǎn)程服務(wù)。

服務(wù)導(dǎo)出需要做的:簡單說就是根據(jù)服務(wù)參數(shù)、服務(wù)協(xié)議構(gòu)建服務(wù)URL,注冊到注冊中心,并啟動Server。其中服務(wù)參數(shù)可以動態(tài)配置也需要監(jiān)聽。
服務(wù)導(dǎo)出入口
1、onApplicationEvent
org.apache.dubbo.config.spring.ServiceBean#onApplicationEvent
發(fā)布ContextRefreshedEvent,進(jìn)行導(dǎo)出服務(wù)

2、export
org.apache.dubbo.config.spring.ServiceBean#export
調(diào)用父類ServiceConfig導(dǎo)出,之后發(fā)布一個ServiceBeanExportedEvent

3、export
org.apache.dubbo.config.ServiceConfig#export

①、檢查更新配置參數(shù)
②、shouldExport檢查服務(wù)是否需要導(dǎo)出
org.apache.dubbo.config.ServiceConfig#shouldExport

③、shouldDelay檢查服務(wù)是否需要延遲發(fā)布


④、doExport進(jìn)行服務(wù)導(dǎo)出
更新配置
checkAndUpdateSubConfigs
org.apache.dubbo.config.ServiceConfig#checkAndUpdateSubConfigs

1、completeCompoundConfigs
ServiceConfig中的某些屬性如果是空的,那么就從ProviderConfig、ModuleConfig、ApplicationConfig中獲取
①、如果配置了ProviderConfig provider,如果application、module、registries、monitor、protocols、configCenter這些屬性為空的情況下,可以從provider中獲取信息并賦值

②、同樣的道理,如果ModuleConfig module不為空,可以為registries、monitor為空的賦值

③、如果ApplicationConfig application不為空,可以為registries、monitor為空的賦值
2、startConfigCenter
從配置中心獲取配置,包括應(yīng)用配置和全局配置

①、如果ConfigCenterConfig ConfigCenter配置中心配置不為空,則需要從其他位置獲取配置中心的相關(guān)屬性信息進(jìn)行更新refresh
org.apache.dubbo.config.AbstractConfig#refresh

a、前綴是prefix = "dubbo.config-center"、id = null 在不同的位置獲取混合的配置CompositeConfiguration

CompositeConfiguration是一個有序的LinkedList
SystemConfiguration(JVM環(huán)境變量系統(tǒng)配置)、EnvironmentConfiguration(操作系統(tǒng)環(huán)境變量)、InmemoryConfiguration(配置中心應(yīng)用配置和全局配置)、PropertiesConfiguration(dubbo.properties中的配置)
b、根據(jù)configCenterFirst配置設(shè)置config的位置。默認(rèn)true第四個位置

參數(shù)配置及優(yōu)先級
SystemConfiguration:是系統(tǒng)環(huán)境變量,可以在服務(wù)啟動時通過-D指定參數(shù)
AbstractConfig:是通過@Service注解配置的參數(shù)
PropertiesConfiguration:是dubbo.properties文件配置的
AppExternalConfiguration和ExternalConfiguration:是在配置中心Dubbo-Admin中配置的,AppXxx是應(yīng)用級別
配置優(yōu)先級是:SystemConfiguration -> AppExternalConfiguration -> ExternalConfiguration -> AbstractConfig -> PropertiesConfiguration
如果放到第二個位置優(yōu)先級是:SystemConfiguration -->AbstractConfig -> AppExternalConfiguration -> ExternalConfiguration -> -> PropertiesConfiguration
c、根據(jù)setXX()方法和setParameters()方法進(jìn)行參數(shù)值覆蓋

②、prepareEnvironment
管理臺上的動態(tài)配置中心,如果是zookeeper,獲取的就是/dubbo/config/dubbo/dubbo.properties節(jié)點(diǎn)中的內(nèi)容。如果是應(yīng)用級別的則獲取的就是/dubbo/config/dubbo-demo-consumer-application/dubbo.properties節(jié)點(diǎn)中的內(nèi)容(dubbo-demo-consumer-application應(yīng)用名,這里是以dubbo-demo為例)

③、refreshAll
ConfigManager.getInstance().refreshAll()刷新所有配置
org.apache.dubbo.config.context.ConfigManager#refreshAll

3、checkDefault 從配置中心設(shè)置Provider配置
org.apache.dubbo.config.ServiceConfig#checkDefault


4、checkProtocol 從配置中心設(shè)置Protocol配置

org.apache.dubbo.config.ServiceConfig#convertProtocolIdsToProtocols

①、從配置中心的全局配置獲取dubbo.protocols.的配置項值添加到configedProtocols
②、從配置中心的應(yīng)用配置獲取dubbo.protocols.的配置項值添加到configedProtocols
③、用,號join所有的protocol(configedProtocols),并賦值給protocolIds

④、如果protocolIds為空,說明配置中心沒有配置協(xié)議,就取默認(rèn)的協(xié)議
⑤、如果配置中心配置協(xié)議(protocolIds不為空),就把從配置中心配置的協(xié)議添加到服務(wù)的協(xié)議列表中
5、checkApplication
如果ApplicationConfig為空,則構(gòu)造一個ApplicationConfig

6、checkRegistry
如果協(xié)議不是injvm本地協(xié)議(isOnlyInJvm),則會從配置中心獲取Registry配置

7、refresh 刷新配置中心配置

8、checkMetadataReport 更新MetadataReportConfig中的屬性為優(yōu)先級最高的配置

9、檢查當(dāng)前服務(wù)是不是一個泛化服務(wù)

10、Local、Stub、Mock
local和stub一樣,不建議使用了。如果Local存根為true,則存根類為interfaceName + "Local"。如果Stub本地存根為true,則存根類為interfaceName + "Stub"


a、checkStubAndLocal
org.apache.dubbo.config.AbstractInterfaceConfig#checkStubAndLocal

b、checkMock

服務(wù)導(dǎo)出
doExport
org.apache.dubbo.config.ServiceConfig#doExport

unexported表示:當(dāng)前服務(wù)已經(jīng)被取消了,就不需要再導(dǎo)出了
exported表示:已經(jīng)導(dǎo)出了,就不再重復(fù)導(dǎo)出了
1、doExportUrls
org.apache.dubbo.config.ServiceConfig#doExportUrls

①、registryURLs
注冊服務(wù)也是一個服務(wù),也會有對應(yīng)的url,通過調(diào)用該url可以完成服務(wù)注冊
registry://127.0.0.1:2181/org.apache.dubbo.registry.RegistryService?application=dubbo-demo-provider1-application&dubbo=2.0.2&logger=log4j&pid=3384®istry=zookeeper&release=2.7.0×tamp=1595994447689
②、遍歷protocols協(xié)議
pathKey = group/應(yīng)用名/path服務(wù)名:version
例如:mygroup/dubbo-demo/org.apache.dubbo.demo.DemoService:1.0.1
ProviderMethodModel表示某一個方法、方法名所屬的服務(wù)的,包含實(shí)現(xiàn)類,接口,以及接口中的各個方法

ApplicationModel表示應(yīng)用中有哪些服務(wù)提供者和引用了哪些服務(wù)
每種協(xié)議都會導(dǎo)出一個單獨(dú)的服務(wù),并注冊到各個注冊中心
2、doExportUrlsFor1Protocol
org.apache.dubbo.config.ServiceConfig#doExportUrlsFor1Protocol


protocolConfig表示協(xié)議配置,registryURLs表示所有的注冊中心URL
①、如果配置的協(xié)議沒有配置name,則默認(rèn)為dubbo
②、map表示服務(wù)url的參數(shù),包括監(jiān)控中心、應(yīng)用、模塊、提供者、協(xié)議、 服務(wù)本身

③、methods方法參數(shù)處理

④、METHODS_KEY = methods 參數(shù)添加

⑤、Token參數(shù)
是為了防止服務(wù)被消費(fèi)者直接調(diào)用(偽造http請求)

⑥、獲取服務(wù)URL 可以通過獲取的host和port訪問該服務(wù)

服務(wù)url
dubbo://192.168.7.81:20881/org.apache.dubbo.demo.DemoService?anyhost=true&application=dubbo-demo-provider1-application&bean.name=ServiceBean:org.apache.dubbo.demo.DemoService&bind.ip=192.168.7.81&bind.port=20881&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&interface=org.apache.dubbo.demo.DemoService&logger=log4j&methods=sayHello&pid=3384&release=2.7.0&side=provider×tamp=1595995315282
⑦、scope導(dǎo)出方式(scope=null進(jìn)行遠(yuǎn)程導(dǎo)出)

scope取值是:null、remote、 local、none
如果scope為none,則不會進(jìn)行任何的服務(wù)導(dǎo)出,既不會遠(yuǎn)程,也不會本地
如果scope不是remote,則會進(jìn)行本地導(dǎo)出,會把當(dāng)前url的protocol改為injvm,然后進(jìn)行導(dǎo)出
如果scope不是local,則會進(jìn)行遠(yuǎn)程導(dǎo)出
如果是injvm,則不需要進(jìn)行注冊中心注冊
⑧、為服務(wù)url添加dynamic、monitor、proxy參數(shù),如果存在的話
如果有注冊中心,則將服務(wù)注冊到注冊中心

⑨、生成Invoker代理對象

Invoker 是實(shí)體域,它是 Dubbo 的核心模型,它代表一個可執(zhí)行體,可向它發(fā)起 invoke 調(diào)用。可參考官網(wǎng)架構(gòu)設(shè)計領(lǐng)域模型
a、生成一個當(dāng)前服務(wù)接口的代理對象invoker。使用代理(默認(rèn)使用javassist)生成一個Invoker,Invoker表示服務(wù)提供者的代理,可以使用Invoker的invoke方法執(zhí)行服務(wù)
參數(shù)包含:服務(wù)的實(shí)現(xiàn)者ref=DemoServiceImpl、服務(wù)接口類interfaceClass=DemoService、服務(wù)的注冊地址url是
registry://127.0.0.1:2181/org.apache.dubbo.registry.RegistryService?application=dubbo-demo-provider1-application&dubbo=2.0.2&export=dubbo%3A%2F%2F192.168.7.81%3A20881%2Forg.apache.dubbo.demo.DemoService%3Fanyhost%3Dtrue%26application%3Ddubbo-demo-provider1-application%26bean.name%3DServiceBean%3Aorg.apache.dubbo.demo.DemoService%26bind.ip%3D192.168.7.81%26bind.port%3D20881%26deprecated%3Dfalse%26dubbo%3D2.0.2%26dynamic%3Dtrue%26generic%3Dfalse%26interface%3Dorg.apache.dubbo.demo.DemoService%26logger%3Dlog4j%26methods%3DsayHello%26pid%3D4824%26release%3D2.7.0%26side%3Dprovider%26timestamp%3D1596073850978&logger=log4j&pid=4824®istry=zookeeper&release=2.7.0×tamp=1596073850955
生成的注冊服務(wù)URL是在registryURL和export參數(shù)是服務(wù)url的拼裝
b、DelegateProviderMetaDataInvoker也表示服務(wù)提供者,包括了Invoker和服務(wù)的配置。是對Invoker的包裹
c、protocol.export(wrapperInvoker)這是導(dǎo)出的核心,使用了SPI。
使用特定的協(xié)議來對服務(wù)進(jìn)行導(dǎo)出,這里的協(xié)議是registry,導(dǎo)出成功后得到一個Exporter
由于注冊地址也是服務(wù),所以會先使用RegistryProtocol進(jìn)行服務(wù)注冊(服務(wù)導(dǎo)出),然后注冊(服務(wù)導(dǎo)出)完了之后,再使用DubboProtocol進(jìn)行導(dǎo)出
自適應(yīng)SPI會獲取url
org.apache.dubbo.config.invoker.DelegateProviderMetaDataInvoker#getUrl

⑩、當(dāng)存在注冊中心時,是先使用Registy協(xié)議注冊服務(wù),然后在使用Http協(xié)議導(dǎo)出服務(wù)。而沒有注冊中心時,是直接使用Http協(xié)議導(dǎo)出服務(wù)。根據(jù)服務(wù)url,講服務(wù)的元信息存入元數(shù)據(jù)中心MetadataReportService
export
RegistryProtocol被ProtocolFilterWrapper包裹,ProtocolFilterWrapper被ProtocolListenerWrapper包裹(SPI原理)
RegistryProtocol
1、export
org.apache.dubbo.rpc.protocol.ProtocolListenerWrapper#export
如果協(xié)議是REGISTRY_PROTOCOL(registry)則會直接走到下一個protocol實(shí)現(xiàn)類ProtocolFilterWrapper。
如果不是則會使用ListenerExporterWrapper處理

2、export
org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper#export
ProtocolFilterWrapper導(dǎo)出同樣的道理,如果是registry則會直接走到下一個。如果不是,則會調(diào)用buildInvokerChain構(gòu)建執(zhí)行代理鏈

3、export
org.apache.dubbo.registry.integration.RegistryProtocol#export

①、獲取registryUrl 將registry://xxx?xx=xx®istry=zookeeper 轉(zhuǎn)為 zookeeper://xx
zookeeper://127.0.0.1:2181/org.apache.dubbo.registry.RegistryService?application=dubbo-demo-provider1-application&dubbo=2.0.2&export=dubbo%3A%2F%2F192.168.7.81%3A20881%2Forg.apache.dubbo.demo.DemoService%3Fanyhost%3Dtrue%26application%3Ddubbo-demo-provider1-application%26bean.name%3DServiceBean%3Aorg.apache.dubbo.demo.DemoService%26bind.ip%3D192.168.7.81%26bind.port%3D20881%26deprecated%3Dfalse%26dubbo%3D2.0.2%26dynamic%3Dtrue%26generic%3Dfalse%26interface%3Dorg.apache.dubbo.demo.DemoService%26logger%3Dlog4j%26methods%3DsayHello%26pid%3D1072%26release%3D2.7.0%26side%3Dprovider%26timestamp%3D1596076187605&logger=log4j&pid=1072&release=2.7.0×tamp=1596076187072
②、獲取providerUrl 服務(wù)提供者url
dubbo://192.168.7.81:20881/org.apache.dubbo.demo.DemoService?anyhost=true&application=dubbo-demo-provider1-application&bean.name=ServiceBean:org.apache.dubbo.demo.DemoService&bind.ip=192.168.7.81&bind.port=20881&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&interface=org.apache.dubbo.demo.DemoService&logger=log4j&methods=sayHello&pid=1072&release=2.7.0&side=provider×tamp=1596076187605
③、生成overrideSubscribeUrl,與監(jiān)聽有關(guān)
在服務(wù)提供者url的基礎(chǔ)上,生成一個overrideSubscribeUrl,協(xié)議為provider://,增加參數(shù)category=configurators&check=false
overrideSubscribeUrl是用來對動態(tài)配置監(jiān)聽的,需要監(jiān)聽的服務(wù)和監(jiān)聽的類型(configurators, 老版本)
一個overrideSubscribeUrl對應(yīng)一個OverrideListener,用來監(jiān)聽overrideSubscribeUrl變化事件
provider://192.168.7.81:20881/org.apache.dubbo.demo.DemoService?anyhost=true&application=dubbo-demo-provider1-application&bean.name=ServiceBean:org.apache.dubbo.demo.DemoService&bind.ip=192.168.7.81&bind.port=20881&category=configurators&check=false&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&interface=org.apache.dubbo.demo.DemoService&logger=log4j&methods=sayHello&pid=1072&release=2.7.0&side=provider×tamp=1596076187605
④、doLocalExport導(dǎo)出
此時服務(wù)協(xié)議是dubbo,DubboProtocol被ProtocolFilterWrapper包裹,ProtocolFilterWrapper被ProtocolListenerWrapper包裹

DubboProtocol
1、export
org.apache.dubbo.rpc.protocol.ProtocolListenerWrapper#export
返回結(jié)果被ListenerExporterWrapper包裹

2、export
org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper#export

①、buildInvokerChain
org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper#buildInvokerChain
根據(jù)url獲取filter,根據(jù)url中的parameters匹配key所對應(yīng)的filter,也會匹配group



EchoFilter、ClassLoaderFilter、GenericFilter、ContextFilter、TraceFilter、TimeoutFilter、MonitorFilter、ExceptionFilter
返回包裹了Filter的CallbackRegistrationInvoker
3、export
org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol#export

獲取url、獲取key、isStubSupportEvent=false、isCallbackservice=false

開啟Server。dubbo協(xié)議是NettyServer。dubbo協(xié)議的mina,netty,http協(xié)議的jetty,servlet等,默認(rèn)為netty
org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol#createServer
其中創(chuàng)建Server,最重要的是通過url綁定端口,和對應(yīng)的請求處理器。requestHandler是請求處理器,類型為ExchangeHandler。表示從url的端口接收到請求后,requestHandler來進(jìn)行處理

4、register
org.apache.dubbo.registry.integration.RegistryProtocol#export
在調(diào)用doLocalExport方法進(jìn)入DubboProtocol協(xié)議開啟Server之后,便會調(diào)用RegistryProtocol的register注冊到注冊中心zookeeper中

registry表示注冊中心,registeredProviderUrl表示存入到注冊中心去的providerUrl,會對其中的參數(shù)進(jìn)行簡化
providerInvokerWrapper表示服務(wù)提供者Invoker、該服務(wù)對應(yīng)的注冊中心地址、簡化后的服務(wù)registeredProviderUrl的包裝類
①、register
org.apache.dubbo.registry.integration.RegistryProtocol#register

②、register
org.apache.dubbo.registry.support.FailbackRegistry#register

③、doRegister
調(diào)用zkClient.create,注冊到zookeeper中


動態(tài)配置監(jiān)聽
在服務(wù)導(dǎo)出過程中,需要對動態(tài)配置中心的數(shù)據(jù)進(jìn)行監(jiān)聽。如果發(fā)生更改,可以及時做出反映。
這里用到了Zookeeper的Watcher機(jī)制。
1、配置中心的路徑與動態(tài)配置路徑是不相同的,這里需要區(qū)分開來
配置中心的路徑是:
①、應(yīng)用:/dubbo/config/dubbo/org.apache.dubbo.demo.DemoService/dubbo.properties節(jié)點(diǎn)的內(nèi)容
②、全局:/dubbo/config/dubbo/dubbo.properties節(jié)點(diǎn)的內(nèi)容
2、對于動態(tài)配置的監(jiān)聽有版本的差別
在2.7之前,只可以對單個服務(wù)進(jìn)行監(jiān)聽,不可以對應(yīng)用監(jiān)聽
/dubbo/org.apache.dubbo.demo.DemoService/configurators/* 只對路徑名字監(jiān)聽,不監(jiān)聽內(nèi)容
在2.7之后,服務(wù)和應(yīng)用都可以監(jiān)聽
服務(wù): /dubbo/config/dubbo/org.apache.dubbo.demo.DemoService.configurators 節(jié)點(diǎn)的內(nèi)容
應(yīng)用: /dubbo/config/dubbo/dubbo-demo-provider-application.configurators 節(jié)點(diǎn)的內(nèi)容
3、監(jiān)聽時機(jī)RegistryProtocol#export
org.apache.dubbo.registry.integration.RegistryProtocol#export

2.6之后版本監(jiān)聽器原理
0、overrideUrlWithConfig
org.apache.dubbo.registry.integration.RegistryProtocol#overrideUrlWithConfig

providerConfigurationListener是RegistryProtocol的一個屬性值,在創(chuàng)建RegistryProtocol類時,便會得到這個應(yīng)用配置的監(jiān)聽器

1、ProviderConfigurationListener 應(yīng)用監(jiān)聽器
應(yīng)用配置,providerConfigurationListener是在屬性那里直接初始化好的,providerConfigurationListener會監(jiān)聽配置中心的應(yīng)用配置信息變動
org.apache.dubbo.registry.integration.RegistryProtocol.ProviderConfigurationListener#ProviderConfigurationListener

org.apache.dubbo.registry.integration.AbstractConfiguratorListener#initWith
①、獲取dynamicConfiguration

②、指定路徑添加監(jiān)聽器addListener
org.apache.dubbo.configcenter.DynamicConfiguration#addListener

org.apache.dubbo.configcenter.support.zookeeper.ZookeeperDynamicConfiguration#addListener

③、獲取路徑getPathKey
org.apache.dubbo.configcenter.support.zookeeper.ZookeeperDynamicConfiguration#getPathKey

所以,key值是dubbo-demo-provider1-application.configurators的監(jiān)聽路徑是
/dubbo/config/dubbo/dubbo-demo-provider1-application.configurators
rawConfig表示從配置中心獲取當(dāng)前應(yīng)用的動態(tài)配置數(shù)據(jù),如果存在應(yīng)用配置信息則根據(jù)配置信息生成Configurator
④、genConfiguratorsFromRawRule
org.apache.dubbo.registry.integration.AbstractConfiguratorListener#genConfiguratorsFromRawRule
先把應(yīng)用或服務(wù)配置轉(zhuǎn)成url,再根據(jù)url生成對應(yīng)的Configurator

2、ServiceConfigurationListener 服務(wù)監(jiān)聽器
ServiceConfigurationListener會監(jiān)聽配置中心的服務(wù)信息配置信息變動,每注冊一個服務(wù)都會生成一個服務(wù)監(jiān)聽器

org.apache.dubbo.registry.integration.RegistryProtocol.ServiceConfigurationListener#ServiceConfigurationListener

org.apache.dubbo.configcenter.support.zookeeper.ZookeeperDynamicConfiguration#getPathKey

key是org.apache.dubbo.demo.DemoService::.configurators,得到的監(jiān)聽路徑是/dubbo/config/dubbo/org.apache.dubbo.demo.DemoService::.configurators
3、把服務(wù)監(jiān)聽添加到serviceConfigurationListeners集合中

2.6以及之前版本監(jiān)聽器原理

org.apache.dubbo.registry.support.FailbackRegistry#subscribe

org.apache.dubbo.registry.zookeeper.ZookeeperRegistry#doSubscribe
進(jìn)行訂閱,先看父類的subscribe方法。訂閱所有服務(wù)


單獨(dú)訂閱某一個服務(wù),根據(jù)監(jiān)聽地址去拿listeners,如果沒有則生成

添加跟zookeeper相關(guān)的ChildListener

這里的urls就是從現(xiàn)在所引入的服務(wù)的目錄下查到的url,比如下面這個三個目錄下的路徑(這里會在服務(wù)引入時,有這些值)
/dubbo/org.apache.dubbo.demo.DemoService/providers
/dubbo/org.apache.dubbo.demo.DemoService/configurators
/dubbo/org.apache.dubbo.demo.DemoService/routers
OverrideListener觸發(fā)
OverrideListener實(shí)現(xiàn)了NotifyListener,OverrideListener訂閱的subscribeUrl發(fā)生改變OverrideListener將會接收到通知
1、notify
org.apache.dubbo.registry.integration.RegistryProtocol.OverrideListener#notify
對發(fā)生了變化的url進(jìn)行過濾,只獲取url是override協(xié)議或參數(shù)category=onfigurators的url

根據(jù)Override協(xié)議修改
2、doOverrideIfNecessary
org.apache.dubbo.registry.integration.RegistryProtocol.OverrideListener#doOverrideIfNecessary
根據(jù)configurators修改url

修改過的newUrl和目前的currentUrl不相同,則重新按newUrl導(dǎo)出

3、reExport
org.apache.dubbo.registry.integration.RegistryProtocol#reExport

根據(jù)newInvokerUrl獲取exporter進(jìn)行導(dǎo)出、得到最新的注冊registryUrl。如果新的服務(wù)url和這個服務(wù)之前的服務(wù)url不相等,則需要把新的服務(wù)url注冊到注冊中心。
4、process
ProviderConfigurationListener和ServiceConfigurationListener都實(shí)現(xiàn)了AbstractConfiguratorListener,所以如果配置發(fā)生了改變將會觸發(fā)org.apache.dubbo.registry.integration.AbstractConfiguratorListener#process方法

org.apache.dubbo.registry.integration.RegistryProtocol.OverrideListener#doOverrideIfNecessary
會調(diào)用子類doOverrideIfNecessary方法
Exporter結(jié)構(gòu)
org.apache.dubbo.registry.integration.RegistryProtocol#doLocalExport調(diào)用之后得到的exporter從外到內(nèi)依次是
RegistryProtocol$ExporterChangeableWrapper、ListenerExporterWrapper、DubboExporter
在org.apache.dubbo.registry.integration.RegistryProtocol#export返回結(jié)果又被DestroyableExporter包裹。

1、DestroyableExporter
org.apache.dubbo.registry.integration.RegistryProtocol.DestroyableExporter#unexport

2、ExporterChangeableWrapper
org.apache.dubbo.registry.integration.RegistryProtocol.ExporterChangeableWrapper#unexport
從注冊中心刪除服務(wù)URL、解綁當(dāng)前服務(wù)的監(jiān)聽器Listener


3、ListenerExporterWrapper
org.apache.dubbo.rpc.listener.ListenerExporterWrapper#unexport
在unexport對應(yīng)服務(wù)之后,把服務(wù)監(jiān)聽器移除

4、AbstractExporter
org.apache.dubbo.rpc.protocol.AbstractExporter#unexport

這幾個Exporter主要在于getInvoker和unexport方法
總結(jié):
dubbo服務(wù)導(dǎo)出的核心就是根據(jù)各種位置的配置構(gòu)建服務(wù)url,并注冊到注冊中心。
還有一點(diǎn)是服務(wù)導(dǎo)出生成的Export結(jié)構(gòu)是為了服務(wù)消費(fèi)端進(jìn)行調(diào)用的。
其中,開啟服務(wù)也是為了與服務(wù)消費(fèi)端進(jìn)行調(diào)用信息的傳輸。