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配置的实现原理和源码,其他方法不再赘述。
文章开头已经提到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大专业测评方法
代码逻辑 吸收能力 技术学习能力 综合素质
先测评确定适合在学习