zoukankan      html  css  js  c++  java
  • 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);
        }

  • 相关阅读:
    IOSNSDate输出string方式小记
    IOSMFMailComposeViewController自定义NavBar
    IOSanimated使用注意
    IOS获取Model(设备型号)、Version(设备版本号)、app(程序版本号)等
    IOSselector注意事项:@selector(showAlertView:)
    IOSOpenURL
    JVM GC, 新生代,旧生代
    PageCache, BufferCache, SwapCache
    java nio(reactor, selector, selectionKey)
    byteBuffer, clear(), flip(), rewind(), allocate(), allocateDirect()
  • 原文地址:https://www.cnblogs.com/wqff-biubiu/p/12488292.html
Copyright © 2011-2022 走看看