美文网首页
Motan 通过配置文件 启动分析

Motan 通过配置文件 启动分析

作者: _流浪的猫_ | 来源:发表于2016-10-29 17:37 被阅读0次

    通过配置文件XML启动,入口处理也是AbstractApplicationContext类中的refresh方法,但xml是在这个调用中处理的ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();如doLoadDocument和registerBeanDefinitions。核心处理在XmlBeanDefinitionReader类的doLoadBeanDefinitions方法中,该方法也就两个函数调用,先加载XML,然后注册bean。

    doLoadDocument方法,将xml加载到内存中,转换为Document对象的示例,fNodeValue存放这节点的值,如下图:(可以看到Motan的一些节点值)


    nodevalue.png

    doLoadBeanDefinitions方法,功能就是将xml描述的bean注册到上下文中。继续往里查看代码,一个核心处理在DefaultBeanDefinitionDocumentReader类的parseBeanDefinitions方法处:

    protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
      if (delegate.isDefaultNamespace(root)) {
       NodeList nl = root.getChildNodes();
       for (int i = 0; i < nl.getLength(); i++) {
        Node node = nl.item(i);
        if (node instanceof Element) {
         Element ele = (Element) node;
         if (delegate.isDefaultNamespace(ele)) {
           // 处理 spring 默认的命名空间的元素,就是xml头上spring自己的一些东西
          parseDefaultElement(ele, delegate);
         }
         else {
          // 处理自定义的元素
          delegate.parseCustomElement(ele);
         }
        }
       }
      }
      else {
       delegate.parseCustomElement(root);
      }
     }
    

    parseCustomElement方法主要处理:

    // handlerMappingsLocation值:META-INF/spring.handlers,spring遍历查找各个工程或包找这个文件,并获取其值
    Properties mappings =
            PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader);
    
    • 用第一步的uri从mappings中查找uri对应的值(命名空间的处理器):
      com.weibo.api.motan.config.springsupport.MotanNamespaceHandler
    • 通过反射构建其实例,并调用其init方法
      MotanNamespaceHandler的init方法注册了Motan各个自定DOM节点的解析器
    • 将MotanNamespaceHandler的实例存入handlerMappings用于后续的解析
    • 找到对应DOM节点的解析器,开始解析,具体看Motan的代码

    后面是实例化、初始化等等各种bean的操作了,与注解的处理还不一样。

    • 首先涉及Motan的方法处理是registerBeanPostProcessors(beanFactory),这里创建ServiceConfigBean的实例

      • 通过invokeAwareMethods处理实现BeanFactoryAware接口的类,给ServiceConfigBean设置beanFactory。
      • 通过invokeInitMethods处理实现了InitializingBean类的的afterPropertiesSet方法。ServiceConfigBean在afterPropertiesSet这里会创建注册中心bean,协议bean
    • registerListeners(),会将serviceconfigbean添加到监听列表,因为其实现了ApplicationListener接口

    • finishRefresh(); 会调用事件(实现ApplicationListener接口的类的onApplicationEvent方法),开始暴露服务


    ServiceConfigBeanbean实现了下面几个接口

    • BeanPostProcessor
      下面是Motan源码,通过断点调试,未见调用该方法.....
    // 为了让serviceBean最早加载
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            return bean;
        }
    
    • BeanFactoryAware 设置beanFactory,用于获取bean
    • InitializingBean 用于一些Motan需要的bean的创建及检测
    • DisposableBean 用于容器关闭时反注册服务
    • ApplicationListener<ContextRefreshedEvent> 用于在spring初始化完之后暴露服务

    serviceBean 实现 InitializingBean接口,在afterPropertiesSet方法中创建必要的bean:
    1、创建serviceBasicConfig的实例(getBean方法)

    • 缓存的单例实例中不存在,找bean的定义
    • 获取实例化策略,根据bean的定义开始创建bean的实例
    • 将bean定义中的值(xml中配置的)设置到新创建的bean中
    • 如果发现引用类型的值,则继续调用getBean获取(此处是要获取注册中心的实例),流程与创建serviceBasicConfig一样。
    • 最后创建完返回,给ServiceConfigBean设置BasicServiceInterfaceConfig的实例

    2、创建协议bean

    • 解析export="demoMotan:8002",获取协议名demoMotan和端口8002
    • 创建ProtocolConfig实例(getBean方法),流程与上面一致
    • 创建完,通过setProtocols设置协议

    3、最后再检查RegistryConfig,以防意外缺少注册中心配置(该配置在第一步中创建过)


    从上面来看,要扩展spring xml语法,需要下面几个步骤

    • 在resource目录下创建META-INF文件夹,并增加两个文件
      (Motan的文件在motan-core工程中)
    • spring.handlers,用来告诉spring自定义的命名空间处理类
    • spring.schemas,用于告诉spring自定义扩展元素的定义文件的位置(xml Schema Definition)
    • 实现NamespaceHandlerSupport接口,在init方法中注册各个元素的解析类
      (Motan参照motan-springsupport中的MotanNamespaceHandler类)
    • 实现BeanDefinitionParser接口,并实现对各个元素的解析处理

    相关文章

      网友评论

          本文标题:Motan 通过配置文件 启动分析

          本文链接:https://www.haomeiwen.com/subject/xrdjuttx.html