Dubbo源码解析:标签分析 - 极悦
首页 课程 师资 教程 报名

Dubbo源码解析:标签分析

  • 2022-03-18 12:18:03
  • 1757次 极悦

1.Dubbo配置方法

Dubbo支持多种配置:

XML配置:基于Spring的Schema和XML扩展机制实现

属性配置:加载ClassPath根目录下的Dubbo.Properties

API配置:硬编码方式配置(不推荐)

注意配置:通过注解配置(Dubbo-2.5.7及以上,不推荐)

对于Property的配置方式,可以通过环境变量指定, -d 启动参数dubbo.properties文件,加载文件的顺序为:

-D 启动参数

环境变量

类路径根目录

加载代码如下:

public  static  final String DUBBO_PROPERTIES_KEY = "dubbo.properties.file" ;
public  static  final String DEFAULT_DUBBO_PROPERTIES = "dubbo.properties" ;
私有 静态 易失性属性属性;
公共 静态属性 getProperties() {
     if (PROPERTIES == null ) {
        同步(ConfigUtils.class ) {
             if ( PROPERTIES == null ) {
                字符串路径= System.getProperty(Constants.DUBBO_PROPERTIES_KEY);
                if (path == null || path.length() == 0 ) {
                    路径= System.getenv(Constants.DUBBO_PROPERTIES_KEY);
                    if (path == null || path.length() == 0 ) {
                        路径=常量.DEFAULT_DUBBO_PROPERTIES;
                    }
                }
                属性= ConfigUtils.loadProperties(路径,假,真);
            }
        }
    }
    返回属性;
}

本文主要分析XML配置的实现原理和源码,其他方法不再赘述。

2.XML配置

文章开头已经提到XML配置是基于Spring-based Schema和XML扩展来实现的。通过这种机制,我们可以编写自己的模式,并根据自定义的 SCHEMA 自定义标签配置 bean。

使用 XML 扩展机制有几个步骤:

定义架构(编写 .xsd 文件)

定义 Javabean

编写 NamespaceHandler 和 BeandefinitionParser 完成 SCHEMA 分析

编写 Spring.Handlers 和 Spring.Schemas 文件系列解析部分

XML 文件中的应用程序配置

Dubbo-Config 模块中的 Dubbo 配置相关代码。

(1)定义模式

Schema的定义体现在.xsd文件中,该文件位于Dubbo-Config-Spring子模块下:

至于XSD的数据类型,如何定义,不是本文的重点。

(2)定义Javabean

Dubbo-Config-API子模块定义了JavaBean的所有配置项,JavaBean中JavaBean的属性,在Dubbo-Config-API子模块中定义。

(3)SCHEMA分析

Dubbo 服务框架的 SCHEMA 由 DubbonamespaceHandler 和 DubbobeandefinitionParser 实现。

其中,DubboNamespaceHandler扩展了 Spring 的 NamespaceHandler 支持,并通过重写其 INIT() 方法注册相应的解析器:

公共 类DubboNamespaceHandler扩展NamespaceHandlerSupport {
    静态{Version.checkDuplicate 
        (DubboNamespaceHandler.class );
    }
    公共 无效初始化(){
        registerBeanDefinitionParser( "应用程序" , new DubboBeanDefinitionParser(ApplicationConfig.class , true ) );
        registerBeanDefinitionParser( "module" , new DubboBeanDefinitionParser(ModuleConfig.class , true ) );
        registerBeanDefinitionParser( "注册表" , new DubboBeanDefinitionParser(RegistryConfig.class , true ) );
        registerBeanDefinitionParser( "monitor" , new DubboBeanDefinitionParser(MonitorConfig.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 DubboBeanDefinitionParser(AnnotationBean.class , true ) );
    }
}

但是DubboBeanDefinitionParser实现了 Spring 的 beandefinitionParser,通过覆盖 parse() 方法将标签解析为对应的 JavaBean:

公共 类DubboBeanDefinitionParser实现BeanDefinitionParser {
     public BeanDefinition parse(Element element, ParserContext parserContext) {
     return parse(element, parserContext, beanClass, required);
    }
    @SuppressWarnings( "unchecked" )
     private  static BeanDefinition parse(Element element,ParserContext parserContext,Class<?> beanClass, boolean required) {
        RootBeanDefinition beanDefinition = new RootBeanDefinition();
        beanDefinition.setBeanClass(beanClass);
        beanDefinition.setLazyInit( false );
        // ...... 省略
        if (ProtocolConfig.class .equals(beanClass)) {
             for (String name : parserContext.getRegistry().getBeanDefinitionNames()) {
                BeanDefinition 定义= parserContext.getRegistry().getBeanDefinition(name);
                PropertyValue 属性= definition.getPropertyValues().getPropertyValue("protocol" );
                如果(属性!= null ){
                    对象值= property.getValue();
                    if (value instanceof ProtocolConfig && id.equals(((ProtocolConfig) value).getName())) {
                        definition.getPropertyValues().addPropertyValue( "protocol", new RuntimeBeanReference(id));
                    }
                }
            }
        } else  if (ServiceBean.class .equals (beanClass)) {
            String className = element.getAttribute("class" );
            if (className != null && className.length() > 0 ) {
                RootBeanDefinition classDefinition = new RootBeanDefinition();
                classDefinition.setBeanClass(ReflectUtils.forName(className));
                classDefinition.setLazyInit( false );
                parseProperties(element.getChildNodes(), classDefinition);
                beanDefinition.getPropertyValues().addPropertyValue( "ref", new BeanDefinitionHolder(classDefinition, id + "Impl" ));
            }
        } else  if (ProviderConfig.class .equals (beanClass)) {
            parseNested(element, parserContext, ServiceBean.class , true , "service", "provider" , id, beanDefinition);
        } else  if (ConsumerConfig.class .equals (beanClass)) {
            parseNested(element, parserContext, ReferenceBean.class , false , "reference", "consumer" , id, beanDefinition);
        }
        // ...... 省略
        return beanDefinition;
    }
}

(4)系列组件

上面我们已经知道了解析实现类,那么Spring怎么知道DubbonamespaceHandler是解析Dubbo标签的呢?这是编写spring.handlers文件的实现。

Spring.handlers 内容如下:

http\: // code.alibabatech.com/schema/dubbo=com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler

然后 Spring的spring.schemas文件得知 Dubbo 标签的 Schema 为 Dubbo.xsd,并以此验证 XML 配置文件的格式。

Spring.schemas 文件内容如下:

http\: // code.alibabatech.com/schema/dubbo/dubbo.xsd=META-INF/dubbo.xsd

文件位置如下:

(5)应用配置

通过以上步骤,Dubbo服务框架完成了标签的功能,用户可以在 Dubbo.xsd 中的应用程序中配置 XML。

选你想看

你适合学Java吗?4大专业测评方法

代码逻辑 吸收能力 技术学习能力 综合素质

先测评确定适合在学习

在线申请免费测试名额
价值1998元实验班免费学
姓名
手机
提交