溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何從源碼分析Dubbo與SpringBoot整合以及進(jìn)行Dubbo啟動(dòng)

發(fā)布時(shí)間:2021-09-29 16:01:34 來源:億速云 閱讀:130 作者:柒染 欄目:云計(jì)算

如何從源碼分析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);
    }

如何從源碼分析Dubbo與SpringBoot整合以及進(jìn)行Dubbo啟動(dòng)

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中去的?

如何從源碼分析Dubbo與SpringBoot整合以及進(jìn)行Dubbo啟動(dòng)

再來看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í)。

向AI問一下細(xì)節(jié)

免責(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)容。

AI