您好,登錄后才能下訂單哦!
如何從源碼分析Dubbo與SpringBoot整合以及進(jìn)行Dubbo啟動(dòng),針對(duì)這個(gè)問題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問題的小伙伴找到更簡(jiǎn)單易行的方法。
在分析Reference是提到過Dubbo會(huì)自動(dòng)引配置類,這里需要注意DubboBootstrapApplicationListener:
registerCommonBeans(BeanDefinitionRegistry registry) { registerInfrastructureBean(registry, ReferenceAnnotationBeanPostProcessor.BEAN_NAME, ReferenceAnnotationBeanPostProcessor.class); registerInfrastructureBean(registry, DubboConfigAliasPostProcessor.BEAN_NAME, DubboConfigAliasPostProcessor.class); registerInfrastructureBean(registry, DubboLifecycleComponentApplicationListener.BEAN_NAME, DubboLifecycleComponentApplicationListener.class); registerInfrastructureBean(registry, DubboBootstrapApplicationListener.BEAN_NAME, DubboBootstrapApplicationListener.class); registerInfrastructureBean(registry, DubboConfigDefaultPropertyValueBeanPostProcessor.BEAN_NAME, DubboConfigDefaultPropertyValueBeanPostProcessor.class); }
public class DubboBootstrapApplicationListener extends OneTimeExecutionApplicationContextEventListener implements Ordered { private final DubboBootstrap dubboBootstrap; public DubboBootstrapApplicationListener() { //這里是一個(gè)單例 this.dubboBootstrap = DubboBootstrap.getInstance(); } //監(jiān)聽事件 @Override public void onApplicationContextEvent(ApplicationContextEvent event) { if (event instanceof ContextRefreshedEvent) { onContextRefreshedEvent((ContextRefreshedEvent) event);//上下文刷新完成事件 } else if (event instanceof ContextClosedEvent) { onContextClosedEvent((ContextClosedEvent) event);//關(guān)閉事件 } } private void onContextRefreshedEvent(ContextRefreshedEvent event) { dubboBootstrap.start(); } private void onContextClosedEvent(ContextClosedEvent event) { dubboBootstrap.stop(); } }
DubboBootstrapApplicationListener 實(shí)現(xiàn)了Spring的事件監(jiān)聽,當(dāng)上下文刷新完成的時(shí)候,會(huì)執(zhí)行dubboBootstrap.start():
public DubboBootstrap start() { //CAS if (started.compareAndSet(false, true)) { ready.set(false); //初始化 initialize(); //Dubbo服務(wù)導(dǎo)出 exportServices(); if (!isOnlyRegisterProvider() || hasExportedServices()) { exportMetadataService(); registerServiceInstance(); } //服務(wù)引用 referServices(); } return this; }
先看exportServices()服務(wù)導(dǎo)出:
private void exportServices() { configManager.getServices().forEach(sc -> { ServiceConfig serviceConfig = (ServiceConfig) sc; serviceConfig.setBootstrap(this); if (exportAsync) { ExecutorService executor = executorRepository.getServiceExporterExecutor(); Future<?> future = executor.submit(() -> { sc.export(); exportedServices.add(sc); }); asyncExportingFutures.add(future); } else { sc.export(); exportedServices.add(sc); } }); }
循環(huán)configManager.getServices()中的數(shù)據(jù)依次執(zhí)行導(dǎo)出,那這些Service是從哪來的?:
public Collection<ServiceConfigBase> getServices() {
return getConfigs(getTagName(ServiceConfigBase.class));
}
最終實(shí)際調(diào)用:
protected <C extends AbstractConfig> Map<String, C> getConfigsMap(String configType) {
return (Map<String, C>) read(() -> configsCache.getOrDefault(configType, emptyMap()));
}
getTagName(ServiceConfigBase.class) 獲取類的標(biāo)簽,這里也就是service。我們之前分析過Dubbo的DubboService注解在注冊(cè)原始類的同時(shí)還會(huì)注冊(cè)ServiceBean。下面看ServiceBean的類結(jié)構(gòu)圖, 它是ServiceConfigBase的一個(gè)子類,那么他是如何放到configsCache中去的?
再來看ServiceConfigBase的父類AbstractConfig,它里面有一個(gè)PostConstruct注解的方法,查看官方解釋:PostConstruct注解用于需要依賴注入完成以執(zhí)行任何初始化之后要執(zhí)行的方法上。必須在類投入使用之前調(diào)用此方法。所有支持依賴注入的類都必須支持該注釋。即使該類不要求注入任何資源,也必須調(diào)用用PostConstruct注釋的方法。也就是說所有的ServiceBean在被Spring初始化之后都會(huì)調(diào)用addIntoConfigManager方法。
@PostConstruct public void addIntoConfigManager() { ApplicationModel.getConfigManager().addConfig(this); }
addIntoConfigManager方法的實(shí)際作用就是向configsCache中緩存:
protected void addConfig(AbstractConfig config, boolean unique) { if (config == null) { return; } write(() -> { Map<String, AbstractConfig> configsMap = configsCache.computeIfAbsent(getTagName(config.getClass()), type -> newMap()); addIfAbsent(config, configsMap, unique); }); }
所以,Dubbo中凡是實(shí)現(xiàn)AbstractConfig接口的類,在被Spring初始化之后,最終都會(huì)被緩存到configManager中。
總結(jié):
1、Dubbo中實(shí)現(xiàn)AbstractConfig接口的Bean,在被Spring初始化之后,都會(huì)被放入configManager。
2、Dubbo通過實(shí)現(xiàn)Spring的監(jiān)聽事件,在上下文刷新完成的時(shí)候開始進(jìn)行Dubbo服務(wù)的初始化和啟動(dòng)。
3、啟動(dòng)引導(dǎo)類dubboBootstrap 是一個(gè)單例。
至此,Dubbo容器的啟動(dòng)分析完成。
關(guān)于如何從源碼分析Dubbo與SpringBoot整合以及進(jìn)行Dubbo啟動(dòng)問題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注億速云行業(yè)資訊頻道了解更多相關(guān)知識(shí)。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。