鉴于大多数人使用dubbo都是在spring环境下的,所以我们优先看依赖spring的dubbo是怎么启动的. 在了解dubbo真正开始启动之前,还有一些初始化的工作要做.

我们从最原始的xml的配置方式看起,虽然现在这种方式随着springboot的兴起已经不是很常见了,但是还是会有不少企业或者遗留项目在使用,而且xml的配置方式算是原理级的了,了解总是没有坏处的.

开始之前

在开始之前我们先看下我们的demo的一些重要配置.

pom.xml

<profiles>
    <!-- For jdk 11 above JavaEE annotation -->
    <profile>
        <id>javax.annotation</id>
        <activation>
            <jdk>[1.11,)</jdk>
        </activation>
        <dependencies>
            <dependency>
                <groupId>javax.annotation</groupId>
                <artifactId>javax.annotation-api</artifactId>
                <version>1.3.2</version>
            </dependency>
        </dependencies>
    </profile>
</profiles>

因为使用的是jdk11而jdk11移除 JavaEE 和 CORBA 模块,JavaFX 也已被移除,所以想要@PostConstruct注解生效需要添加上边的profile,否则启动失败.

No application config found or it's not a valid config! Please add <dubbo:application name="..." /> to your spring config.

spring.xml

<dubbo:application name="dubbo-provider-sample"/>
<!-- 使用multicast广播注册中心暴露服务地址 -->
<dubbo:registry address="multicast://224.5.6.7:1234" register="false"/>
<dubbo:protocol name="dubbo"/>

<!-- 声明需要暴露的服务接口 -->
<dubbo:service interface="li.dongpo.tc.SampleService"
                ref="sampleServiceImpl" />

DubboNamespaceHandler

dubbo的配置有专用的标签<dubbo>,spring提供自定义标签的方式就是NamespaceHandler,通过实现NamespaceHandler接口的方式可以自定义标签.

关于自定义标签的部分就不展开了,网上资料非常多,而且现在都是springboot了这种方式也不常见了.

简单来说,DubboNamespaceHandler就是用来解析spring配置文件中<dubbo:xxxx/>这类标签的,每个dubbo标签根据xxxx的不同注入不同的bean,每行配置类似于springboot中的一个@Bean注解.

registerBeanDefinitionParser("application", new DubboBeanDefinitionParser(ApplicationConfig.class, true));
registerBeanDefinitionParser("module", new DubboBeanDefinitionParser(ModuleConfig.class, true));
registerBeanDefinitionParser("registry", new DubboBeanDefinitionParser(RegistryConfig.class, true));
registerBeanDefinitionParser("config-center", new DubboBeanDefinitionParser(ConfigCenterBean.class, true));
registerBeanDefinitionParser("metadata-report", new DubboBeanDefinitionParser(MetadataReportConfig.class, true));
registerBeanDefinitionParser("monitor", new DubboBeanDefinitionParser(MonitorConfig.class, true));
registerBeanDefinitionParser("metrics", new DubboBeanDefinitionParser(MetricsConfig.class, true));
registerBeanDefinitionParser("ssl", new DubboBeanDefinitionParser(SslConfig.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 AnnotationBeanDefinitionParser());

关于这个配置可以参见 dubbo-基础用法-provider-配置

所以xml中的配置 <dubbo:application name=“dubbo-provider-sample”/> 就开始生效了,注入了一个ApplicationConfig. 需要注意的是ApplicationConfig是AbstractConfig的一个子类,而AbstractConfig中包含@PostConstruct注解,所以在注入的时候会执行ApplicationModel.getConfigManager().addConfig(this) 下边的RegistryConfig也是一样的.

ApplicationModel.getConfigManager()这行开始执行的时候,dubbo的扩展机制(ExtensionLoader)就开始初始化了. 这个扩展机制比较重要我们后续展开说.