dubbo系列之xml解析原理NamespaceHandler(二)

621 阅读2分钟

欢迎关注公众号【sharedCode】致力于主流中间件的源码分析, 可以直接与我联系

前言

上一节中我们基于springboot搭建了dubbo的基本用例,能够使用dubbo的基本功能,在dubbo重新开源之前,大部分人都是通过spring的xml文件进行配置的,基于这个背景,有必要讲一下dubbo是怎么解析xml文件,生成代理对象的。

版本说明

springboot starter : 0.1.1

dubbo版本: 2.6.2

DubboNamespaceHandler

这个是dubbo基于spring的扩展点用来解析xml文件的类

public class DubboNamespaceHandler extends NamespaceHandlerSupport {

    static {
        Version.checkDuplicate(DubboNamespaceHandler.class);
    }

    @Override
    public void init() {
        // 解析<dubbo:application/>标签  全局配置,用于配置当前应用信息,不管该应用是提供者还是消费者
        registerBeanDefinitionParser("application", new DubboBeanDefinitionParser(ApplicationConfig.class, true));
        // 解析<dubbo:module/>标签  模块配置 , 用于配置当前模块信息
        registerBeanDefinitionParser("module", new DubboBeanDefinitionParser(ModuleConfig.class, true));
        // 解析<dubbo:registry/>标签  用于配置连接注册中心相关信息
        registerBeanDefinitionParser("registry", new DubboBeanDefinitionParser(RegistryConfig.class, true));
        // 解析<dubbo:monitor/>标签  用于配置连接监控中心相关信息
        registerBeanDefinitionParser("monitor", new DubboBeanDefinitionParser(MonitorConfig.class, true));
        // 解析<dubbo:provider/>标签   当 ProtocolConfig 和 ServiceConfig 某属性没有配置时,采用此缺省值,可选
        registerBeanDefinitionParser("provider", new DubboBeanDefinitionParser(ProviderConfig.class, true));
        // 解析<dubbo:consumer/>标签  当 ReferenceConfig 某属性没有配置时,采用此缺省值,可选
        registerBeanDefinitionParser("consumer", new DubboBeanDefinitionParser(ConsumerConfig.class, true));
        // 解析<dubbo:protocol/>标签   协议
        registerBeanDefinitionParser("protocol", new DubboBeanDefinitionParser(ProtocolConfig.class, true));
        // 解析<dubbo:service/>标签   用于暴露一个服务,定义服务的元信息,一个服务可以用多个协议暴露,一个服务也可以注册到多个注册中心
        registerBeanDefinitionParser("service", new DubboBeanDefinitionParser(ServiceBean.class, true));
        // 解析<dubbo:reference/> 标签  用于创建一个远程服务代理,一个引用可以指向多个注册中心
        registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false));
        // 解析<dubbo:annotation/>标签
        registerBeanDefinitionParser("annotation", new AnnotationBeanDefinitionParser());
    }

}

spring解析

 protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
        if(delegate.isDefaultNamespace(root)) {//是否是默认的NameSpace,Dubbo Namespace不是默认的
            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)) {
                        this.parseDefaultElement(ele, delegate);
                    } else {
                        delegate.parseCustomElement(ele);
                    }
                }
            }
        } else {
        //通过代理来解析Dubbo配置文件中 Element 元素
            delegate.parseCustomElement(root);
        }

 }
public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
        //通过元素获取namespaceURI
        String namespaceUri = this.getNamespaceURI(ele);
        //如 ele:name 为 dubbo:application ,则namespaceUri  = http://code.alibabatech.com/schema/dubbo
        //通过NameSpaceURi 获取NamespaceHandler ,Dubbo对应的是DubboNameSpaceHandler 
        NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver()
        .resolve(namespaceUri);
        if(handler == null) {
            this.error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
            return null;
        } else {
            //DubboBeanDefinitionParser的parse解析
            return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
        }
    }

NamespaceHandlerSupport

spring的自定义schema标签解析是通过写一个继承自NamespaceHandlerSupport的类,并实现init方法,在init方法中,去注册解析器,然后在解析xml的是,通过约定的key去map中拿到相应的解析去解析。

registerBeanDefinitionParser是一个map

spring容器在启动的时候,遇到自定义标签的时候,会通过标签名称去registerBeanDefinitionParser中寻找标签解析器,然后调用标签解析器中的parse方法,得到BeanDefinition,最后实例化bean.

所以dubbo的xml解析原理就是这样的,基于spring的NamespaceHandler的机制,然后通过标签对应的解析器进行解析,最后实例化bean

欢迎关注公众号【sharedCode】致力于主流中间件的源码分析, 可以直接与我联系