课程链接: https://www.itwangzi.cn/2555.html
开始之前,源码基于目前Dubbo3.0.7版本;解读可能是目前文档源码有些出入,请注意版本。
Dubbo和Spring部分
Dubbo支持Spring的xml方式
基本使用和案例
其他书籍或者教程;通常会为你编写一个,HelloWorld的案例;笔者觉得,看这篇文章的读者的水平应该是达到了这个级别的;不在手写Dubbo的入门案例;Dubbo官方源码 dubbo-demo提供好了源码案例。
- 服务提供者编写:
- 服务消费者编写:
- 服务提供者、消费者主类(篇幅问题;提供链接)provider/Applicationconsumer/Application
总结:
通知配置Dubbo标签,Spring容器启动时,加载Dubbo相关的Bean,同时生成对应的接口代理,为RPC调用做好准备。
「思考:(源码阅读需要解决问题)」
- Dubbo如何支持Spring的?
- Dubbo通过代理Bean,实现Spring注入和RPC调用,那么注入哪些Bean,具体细节如何呢?
有了问题,让我们带着问题点阅读源码可能效果更好。
源码解读:
Dubbo在利用Spring可扩展的XML Schema机制时,在Spring启动时加载Dubbo自定义的标签内容(Dubbo的ximl文档[官方文档]);Dubbo的标签较多,这里依照 dubbo:service 配置(dubbo-service文档)为例;可以大体熟悉一下基本用法。
dubbo:service
dubbo:service 配置
服务提供者暴露服务配置。对应的配置类:org.apache.dubbo.config.「ServiceConfig」
属性对应URL参数类型是否必填缺省值作用描述兼容性interfaceclass「必填」 服务发现服务接口名1.0.0以上版本refobject「必填」 服务发现服务对象实现引用
「Spring可扩展的XML Schema机制」

「创建一个 XML Schema 文件,描述自定义的合法构建模块,也就是xsd文件」
dubbo-config/dubbo-config-spring/src/main/resources/META-INF/「dubbo.xsd」
「自定义个处理器类,并实现NamespaceHandler接口(比较容易)」
- 自定义接口handler实现;懂点实现 parse接口:
- init(): NamespaceHandler被使用之前调用,完成NamespaceHandler的初始化
- BeanDefinition parse(Element, ParserContext): 当遇到顶层元素时被调用
- BeanDefinition decorate(Node,BeanDefinitionHandler,ParserContext): 当遇到一个属性或者嵌套元素的时候调用
- 自定义BeanDefinitionParser实现NamespaceHandlerSupport接口;主要解析对应的BeanDefinationorg.apache.dubbo.config.spring.schema.「DubboBeanDefinitionParser」;有兴趣自行分析
- 注册handler和schema
为了让Spring在解析xml的时候能够感知到我们的自定义元素,我们需要把namespaceHandler和xsd文件放到2个指定的配置文件中,这2个文件都位于META-INF目录中Spring通过XML解析程序将其解析为DOM树,通过NamespaceHandler指定对应的Namespace的BeanDefinitionParser将其转换成BeanDefinition。再通过Spring自身的功能对BeanDefinition实例化对象。
在期间,Spring还会加载两项资料:
- 「META-INF/spring.handlers」 指定NamespaceHandler(实现org.springframework.beans.factory.xml.NamespaceHandler)接口,或使用org.springframework.beans.factory.xml.NamespaceHandlerSupport的子类。
- 「META-INF/spring.schemas」 在解析XML文件时将XSD重定向到本地文件,避免在解析XML文件时需要上网*载下**XSD文件。通过现实org.xml.sax.EntityResolver接口来实现该功能
- 对于注册Context容器;这里是Spring自定义机制;目前由于篇幅问题;多做过多的细节介绍:(请看图)
Spring Bean 加载流程分析(通过 XML 方式加载)
Spring-ClassPathXmlApplicationContext源码探讨-解析XML文件_半笙彷徨的博客-CSDN博客
Spring 的annotation部分源码
基本使用和案例

服务接口

服务提供者:

\
源码解读
使用注解需要重点关注:@PropertySource、@DubboService、@DubboReference 就可以了
思考:
- Dubbo的注解都干了些啥?(这个基本看下注释和源码基本都可以明白)
- Dubbo如何如何让Spring识别Dubbo自定义的注解呢?
- 还记得之前注解对应的properties文件吗?这个也作为小问题点
源码入口 -- @EnableDubbo
- @「EnableDubboConfig」 :加载Dubbo相关配置需要配置多个对象(ApplicationConfig、RegistryConfig、ProtocolConfig、ServiceConfig等),而这个注解的目的就是帮我们简化这些配置,只要将相应的配置项通过.properties文件交由@PropertySource注解由Spring加载到Environment中,Dubbo即可通过Environment中相应的属性与ApplicationConfig对象同名的属性进行绑定,而这个过程都是自动。
- @「DubboComponentScan」:扫描类路径以获取将自动注册为Spring bean的注释组件。\
@EnableDubboConfig
@Import(DubboConfigConfigurationRegistrar.class)注解导入;用于解析和加载通用的Bean :
// ImportBeanDefinitionRegistrar 注解 配合 @Import使用public class DubboConfigConfigurationRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { // initialize dubbo beans(Spring从初始化,加载Dubbo相关的Bean) DubboSpringInitializer.initialize(registry); // Config beans creating from props have move to ConfigManager// AnnotationAttributes attributes = AnnotationAttributes.fromMap(// importingClassMetadata.getAnnotationAttributes(EnableDubboConfig.class.getName()));//// boolean multiple = attributes.getBoolean("multiple");//// // Single Config Bindings// registerBeans(registry, DubboConfigConfiguration.Single.class);//// if (multiple) { // Since 2.6.6 https://github.com/apache/dubbo/issues/3193// registerBeans(registry, DubboConfigConfiguration.Multiple.class);// } }}
DubboBeanUtils#registerCommonBeans
/** * Register the common beans * * @param registry {@link BeanDefinitionRegistry} * @see ReferenceAnnotationBeanPostProcessor * @see DubboConfigDefaultPropertyValueBeanPostProcessor * @see DubboConfigAliasPostProcessor * @see DubboBootstrapApplicationListener */ static void registerCommonBeans(BeanDefinitionRegistry registry) { registerInfrastructureBean(registry, ServicePackagesHolder.BEAN_NAME, ServicePackagesHolder.class); registerInfrastructureBean(registry, ReferenceBeanManager.BEAN_NAME, ReferenceBeanManager.class); // Since 2.5.7 Register @Reference Annotation Bean Processor as an infrastructure Bean registerInfrastructureBean(registry, ReferenceAnnotationBeanPostProcessor.BEAN_NAME, ReferenceAnnotationBeanPostProcessor.class); // TODO Whether DubboConfigAliasPostProcessor can be removed ? // Since 2.7.4 [Feature] https://github.com/apache/dubbo/issues/5093 registerInfrastructureBean(registry, DubboConfigAliasPostProcessor.BEAN_NAME, DubboConfigAliasPostProcessor.class); // Since 2.7.4 Register DubboBootstrapApplicationListener as an infrastructure Bean// registerInfrastructureBean(registry, DubboBootstrapApplicationListener.BEAN_NAME,// DubboBootstrapApplicationListener.class); // register ApplicationListeners registerInfrastructureBean(registry, DubboDeployApplicationListener.class.getName(), DubboDeployApplicationListener.class); registerInfrastructureBean(registry, DubboConfigApplicationListener.class.getName(), DubboConfigApplicationListener.class); // Since 2.7.6 Register DubboConfigDefaultPropertyValueBeanPostProcessor as an infrastructure Bean registerInfrastructureBean(registry, DubboConfigDefaultPropertyValueBeanPostProcessor.BEAN_NAME, DubboConfigDefaultPropertyValueBeanPostProcessor.class); // Dubbo config initializer registerInfrastructureBean(registry, DubboConfigBeanInitializer.BEAN_NAME, DubboConfigBeanInitializer.class); // register infra bean if not exists later registerInfrastructureBean(registry, DubboInfraBeanRegisterPostProcessor.BEAN_NAME, DubboInfraBeanRegisterPostProcessor.class); }
总结:
使用 @EnableDubbo加载Dubbo对应的共有配置Bean和postprocesser,扫描注解,加载@Service和@reference注解。更多内容启示关于Spring的框架的底层内容熟悉,Dubbo只是灵活的使用Spring的API。