dubbo——spring初始化

研究dubbo就先从自己最感兴趣的开始吧

一、构建dubbo源码环境

① dubbo源码在github中,右上角fork一个分支到自己的github,然后直接git clone拉代码到本地。(用手机热点拉代码有惊喜)

② 改阿里云镜像,maven的settings.xml

  <localRepository>D:/mavenRepository</localRepository>
  <mirrors>
     <mirror>
        <id>nexus-aliyun</id>
        <mirrorOf>*</mirrorOf>
        <name>Nexus aliyun</name>
        <url>http://maven.aliyun.com/nexus/content/groups/public</url>
    </mirror> 
  </mirrors>

③ 导入maven项目到idea中,等待jar依赖下载。

前期学习目标:主要是过一遍源码流程,网上看的架构图都太抽象了,看完源码之后,再去理解。

二、配置解析

官方已经推荐注解形式配置dubbo的服务了,由于工作时用的都是xml配置文件配置dubbo的服务,直接从源码查找注解解析对于我来说有点无从下手的感觉。还是从xml配置文件入手顺手一点。dubbo-demo>dubbo-demo-xml>dubbo-demo-xml-provider下的一个提供xml配置例子。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
       http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">

    <dubbo:application metadata-type="remote" name="demo-provider"/>
    <dubbo:metadata-report address="zookeeper://127.0.0.1:2181"/>

    <dubbo:registry address="zookeeper://127.0.0.1:2181"/>

    <dubbo:protocol name="dubbo"/>

    <bean id="demoService" class="org.apache.dubbo.demo.provider.DemoServiceImpl"/>

    <dubbo:service interface="org.apache.dubbo.demo.DemoService" ref="demoService"/>

</beans>

通过spring.handlers文件找到dubbo命名空间的解析类

/* dubbo-config/dubbo-config-spring/src/main/resources/META-INF/spring.handlers */
http\://dubbo.apache.org/schema/dubbo=org.apache.dubbo.config.spring.schema.DubboNamespaceHandler
http\://code.alibabatech.com/schema/dubbo=org.apache.dubbo.config.spring.schema.DubboNamespaceHandler

Apache和阿里巴巴版本的命名空间进行了统一,指向的是一个命名空间解析类

/* org.apache.dubbo.config.spring.schema.DubboNamespaceHandler#init */
    public void init() {
        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());
    }

前面spring——scan()中是根据注解解析成BeanDefinition,还没有研究过xml解析过程,这里走一遍吧,看看什么时候会调用上面init方法

/* AbstractApplicationContex.refresh()-->
AbstractApplicationContext.obtainFreshBeanFactory()-->
AbstractRefreshableApplicationContext.refreshBeanFactory()-->
AbstractXmlApplicationContext.loadBeanDefinitions()-->
AbstractXmlApplicationContext.loadBeanDefinitions()(重载方法)-->
AbstractBeanDefinitionReader.loadBeanDefinitions()-->
XmlBeanDefinitionReader.loadBeanDefinitions()-->
XmlBeanDefinitionReader.loadBeanDefinitions()(重载方法)-->
XmlBeanDefinitionReader.doLoadBeanDefinitions()-->
XmlBeanDefinitionReader.registerBeanDefinitions()-->
DefaultBeanDefinitionDocumentReader.registerBeanDefinitions()-->
DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions()-->
DefaultBeanDefinitionDocumentReader.parseBeanDefinitions()-->
BeanDefinitionParserDelegate.parseCustomElement()-->
BeanDefinitionParserDelegate.parseCustomElement()(重载方法)*/

    public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
        //解析根节点时,获取xml根节点的xmlns属性,然后缓存起来
        //dubbo的是http://dubbo.apache.org/schema/dubbo
        String namespaceUri = getNamespaceURI(ele);
        //初始化NamespaceHandler
        //① 获取META-INF/spring.handlers文件得到指定NamespaceHandler的className
        //   dubbo是org.apache.dubbo.config.spring.schema.DubboNamespaceHandler
        //② 反射初始化并调用NamespaceHandler.init()注册所有的节点解析器
        //③ 返回namespaceHandler
        NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
        if (handler == null) {
            error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
            return null;
        }
        //namespaceHandle根据子节点名找到解析类,解析标签生成BeanDefinition
        return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
    }

DubboNamespaceHandler.parse():标签节点解析

/* org.apache.dubbo.config.spring.schema.DubboNamespaceHandler#parse */
    public BeanDefinition parse(Element element, ParserContext parserContext) {
        //获取BeanFactory
        BeanDefinitionRegistry registry = parserContext.getRegistry();
        //注解注解相关的解析器
        registerAnnotationConfigProcessors(registry);
        //注册两个监听器
        //DubboLifecycleComponentApplicationListener
        //DubboBootstrapApplicationListener(处理服务注册逻辑,IOC初始化refresh的最后一步finishrefresh())
        registerApplicationListeners(registry);
        //标签节点解析为BeanDefinition
        BeanDefinition beanDefinition = super.parse(element, parserContext);
        setSource(beanDefinition);
        return beanDefinition;
    }

总结:springIOC初始化主要完成两个任务

1、提前初始化注解解析器,注册两个监听器,一个用于生命周期监听,一个用于serviceBean注册到注册表

2、将标签解析成bean,并生成实例

3、注册到注册表(DubboBootstrapApplicationListener.onApplicationEvent())

  

补充:

1、上面所有Config都继承了AbstractConfig,需要注意的是AbstractConfig的一个方法被@PostConstruct注解。

@PostConstruct注解:Bean初始化(DI)后,BeanPostProcessor处理器会以反射的方式,使bean实例执行此方法。

这里addIntoConfigManager()方法作用:将上面所有的config信息,都放入configManager中。

    @PostConstruct
    public void addIntoConfigManager() {
        ApplicationModel.getConfigManager().addConfig(this);
    }

 

posted on 2020-03-13 18:45  FFStayF  阅读(805)  评论(0编辑  收藏  举报