(前言:以provider消费者为例进行说明)

一. 配置参数解析入口

1.provider 配置参数解析入口:
ServiceBean 实现 ApplicationListener(spring 资源解析)重写onApplicationEvent()方法,提供暴露服务

    @Overridepublic void onApplicationEvent(ContextRefreshedEvent event) {if (isDelay() && !isExported() && !isUnexported()) {if (logger.isInfoEnabled()) {logger.info("The service ready on spring started. service: " + getInterface());}export(); //入口}}

二.xxx.properties缺省配置

@From:《dubbo文档-配置-属性配置》

如果公共配置很简单,没有多注册中心,多协议等情况,或者想多个 Spring 容器想共享配置,可以使用 dubbo.properties 作为缺省配置

Dubbo 将自动加载 classpath 根目录下的 dubbo.properties,可以通过JVM启动参数 -Ddubbo.properties.file=xxx.properties 改变缺省配置位置。[1]

测试缺省配置:

org.apache.dubbo.config.AbstractInterfaceConfig#checkApplication#checkApplication() 获取属性信息
// org.apache.dubbo.config.AbstractInterfaceConfig#checkApplication#checkApplication()protected void checkApplication() {// for backward compatibilityif (application == null) {String applicationName = ConfigUtils.getProperty("dubbo.application.name");//提取配置信息 @sjt 1if (applicationName != null && applicationName.length() > 0) {application = new ApplicationConfig();}}

@sjt1: 获取dubbo.application.name的配置信息

org.apache.dubbo.common.utils.ConfigUtils#getProperties()获取jvm文件
 // org.apache.dubbo.common.utils.ConfigUtils#getProperties()public static Properties getProperties() {if (PROPERTIES == null) {synchronized (ConfigUtils.class) {if (PROPERTIES == null) {String path = System.getProperty(Constants.DUBBO_PROPERTIES_KEY); //DUBBO_PROPERTIES_KEY = "dubbo.properties.file"if (path == null || path.length() == 0) {path = System.getenv(Constants.DUBBO_PROPERTIES_KEY);if (path == null || path.length() == 0) {path = Constants.DEFAULT_DUBBO_PROPERTIES; //加载默认文件  DEFAULT_DUBBO_PROPERTIES = "dubbo.properties"}}PROPERTIES = ConfigUtils.loadProperties(path, false, true);}}}return PROPERTIES;}

三.映射规则

属性配置和xml配置的映射规则。就是参数配置的不同方式

eg:
dubbo.application.name=foo 等价于 <dubbo:application name="foo" />

四.覆盖策略

jvm启动 > xml-配置 > dubbo.properties

  • JVM 启动 -D 参数优先,这样可以使用户在部署和启动时进行参数重写,比如在启动时需改变协议的端口
  • XML 次之,如果在 XML 中有配置,则 dubbo.properties 中的相应配置项无效。
  • Properties 最后,相当于缺省值,只有 XML 没有配置时,dubbo.properties 的相应配置项才会生效,通常用于共享公共配置(全局配置),比如应用名。

测试:覆盖策略:

准备参数:

  • jvm:-Ddubbo.protocol.port=20880 -Ddubbo.protocol.id=jvm-id
  • xml:<dubbo:protocol port=“20881” id=“xml-id” />
  • dubbo.properties:dubbo.protocol.port=20882 dubbo.protocol.id=properties-name

准备参数:

  • jvm:-Ddubbo.protocol.port=20880 -Ddubbo.protocol.id=jvm-id
  • xml:<dubbo:protocol port=“20881” id=“xml-id” />
  • dubbo.properties:dubbo.protocol.port=20882 dubbo.protocol.id=properties-name

准备参数:

  • jvm:-Ddubbo.protocol.port=20880 -Ddubbo.protocol.id=jvm-id
  • xml:<dubbo:protocol port=“20881” id=“xml-id” />
  • dubbo.properties:dubbo.protocol.port=20882 dubbo.protocol.id=properties-name

源码解读:org.apache.dubbo.config.AbstractConfig#appendProperties()

 /*** @param config 配置对象* @Description: 读取启动参数变量和 properties 配置到配置对象。*/protected static void appendProperties(AbstractConfig config) {//。。。省略Method[] methods = config.getClass().getMethods();for (Method method : methods) {try {String name = method.getName();if (name.length() > 3 && name.startsWith("set") && Modifier.isPublic(method.getModifiers())// 方法是 public 的 setting 方法。&& method.getParameterTypes().length == 1 && isPrimitive(method.getParameterTypes()[0])) {// 方法的唯一参数是基本数据类型// 获得属性名,例如 `ApplicationConfig#setName(...)` 方法,对应的属性名为 name 。String property = StringUtils.camelToSplitName(name.substring(3, 4).toLowerCase() + name.substring(4), ".");// 【启动参数变量】优先从带有 `Config#id` 的配置中获取,例如:`dubbo.application.demo-provider.name` 。String value = null;if (config.getId() != null && config.getId().length() > 0) {String pn = prefix + config.getId() + "." + property;// 带有 `Config#id`value = System.getProperty(pn);if (!StringUtils.isBlank(value)) {logger.info("Use System Property " + pn + " to config dubbo");}}// 【启动参数变量】获取不到,其次不带 `Config#id` 的配置中获取,例如:`dubbo.application.name` 。if (value == null || value.length() == 0) {String pn = prefix + property;//不带 `Config#id`value = System.getProperty(pn);if (!StringUtils.isBlank(value)) {logger.info("Use System Property " + pn + " to config dubbo");}}if (value == null || value.length() == 0) {// 覆盖优先级为:启动参数变量 > XML 配置 > properties 配置,因此需要使用 getter 判断 XML 是否已经设置Method getter;try {getter = config.getClass().getMethod("get" + name.substring(3));} catch (NoSuchMethodException e) {try {getter = config.getClass().getMethod("is" + name.substring(3));} catch (NoSuchMethodException e2) {getter = null;}}if (getter != null) {if (getter.invoke(config) == null) {// 使用 getter 判断 XML 是否已经设置// 【properties 配置】优先从带有 `Config#id` 的配置中获取,例如:`dubbo.application.demo-provider.name` 。if (config.getId() != null && config.getId().length() > 0) {value = ConfigUtils.getProperty(prefix + config.getId() + "." + property);}// 【properties 配置】获取不到,其次不带 `Config#id` 的配置中获取,例如:`dubbo.application.name` 。if (value == null || value.length() == 0) {value = ConfigUtils.getProperty(prefix + property);}// 【properties 配置】老版本兼容,获取不到,最后不带 `Config#id` 的配置中获取,例如:`dubbo.protocol.name` 。if (value == null || value.length() == 0) {String legacyKey = legacyProperties.get(prefix + property);if (legacyKey != null && legacyKey.length() > 0) {value = convertLegacyValue(legacyKey, ConfigUtils.getProperty(legacyKey));}}}}}// 获取到值,进行反射设置。if (value != null && value.length() > 0) {method.invoke(config, convertPrimitive(method.getParameterTypes()[0], value));}}} catch (Exception e) {logger.error(e.getMessage(), e);//逻辑中间发生异常,不抛出异常,仅打印错误日志。}}

step1:从jvm启动参数获取:

// 【启动参数变量】获取不到,其次不带 `Config#id` 的配置中获取,例如:`dubbo.application.name` 。if (value == null || value.length() == 0) {String pn = prefix + property;//不带 `Config#id`value = System.getProperty(pn);if (!StringUtils.isBlank(value)) {logger.info("Use System Property " + pn + " to config dubbo");}}

step2:判断 XML 是否已经设置:

 if (getter.invoke(config) == null) {// 使用 getter 判断 XML 是否已经设置

step3:ConfigUtils.getProperty()从获取dubbo.properties参数

 if (getter != null) {if (getter.invoke(config) == null) {// 使用 getter 判断 XML 是否已经设置// 【properties 配置】优先从带有 `Config#id` 的配置中获取,例如:`dubbo.application.demo-provider.name` 。if (config.getId() != null && config.getId().length() > 0) {value = ConfigUtils.getProperty(prefix + config.getId() + "." + property);}// 【properties 配置】获取不到,其次不带 `Config#id` 的配置中获取,例如:`dubbo.application.name` 。if (value == null || value.length() == 0) {value = ConfigUtils.getProperty(prefix + property);}// 【properties 配置】老版本兼容,获取不到,最后不带 `Config#id` 的配置中获取,例如:`dubbo.protocol.name` 。if (value == null || value.length() == 0) {String legacyKey = legacyProperties.get(prefix + property);if (legacyKey != null && legacyKey.length() > 0) {value = convertLegacyValue(legacyKey, ConfigUtils.getProperty(legacyKey));}}}

注意:

@From:《dubbo文档-配置-属性配置》

1.如果 classpath 根目录下存在多个 dubbo.properties,比如多个 jar 包中有 dubbo.properties,Dubbo 会任意加载,并打印 Error 日志,后续可能改为抛异常。 ↩

2.协议的 id 没配时,缺省使用协议名作为 id ↩

6.[dubbo源码解析]-属性配置相关推荐

  1. 精尽 Dubbo 源码分析 —— API 配置

    1. 概述 Dubbo 的配置目前提供了四种配置方式:1. API 配置 2. 属性配置 3. XML 配置 4. 注解配置 2. 配置一览 我们来看看 dubbo-config-api 的项目结构, ...

  2. dubbo源码解析(九)远程通信——Transport层

    远程通讯--Transport层 目标:介绍Transport层的相关设计和逻辑.介绍dubbo-remoting-api中的transport包内的源码解析. 前言 先预警一下,该文篇幅会很长,做好 ...

  3. dubbo源码解析(二)

    大家好,我是烤鸭: dubbo 源码解析: 1.服务导出 介绍: Dubbo 服务导出过程始于 Spring 容器发布刷新事件,Dubbo 在接收到事件后,会立即执行服务导出逻辑.整个逻辑大致可分为三 ...

  4. dubbo源码解析(十)远程通信——Exchange层

    远程通讯--Exchange层 目标:介绍Exchange层的相关设计和逻辑.介绍dubbo-remoting-api中的exchange包内的源码解析. 前言 上一篇文章我讲的是dubbo框架设计中 ...

  5. Dubbo源码解析 —— Router

    作者:肥朝 原文地址:http://www.jianshu.com/p/278e782eef85 友情提示:欢迎关注公众号[芋道源码].????关注后,拉你进[源码圈]微信群和[肥朝]搞基嗨皮. 友情 ...

  6. Dubbo源码解析-Dubbo服务消费者_Dubbo协议(一)

    前言: 在介绍完Dubbo 本地模式(Injvm协议)下的服务提供与消费后,上文我们又介绍了Dubbo远程模式(dubbo协议)下的服务暴露过程,本质上就是通过Netty将dubbo协议端口暴露出去, ...

  7. Dubbo源码解析 --- DIRECTORY和ROUTER

    Dubbo源码解析 --- DIRECTORY和ROUTER 今天看一下Directory和Router. 我们直接从代码看起(一贯风格),先看后总结,对着总结再来看,相信会收获很多.我们先看com. ...

  8. dubbo源码解析-集群容错架构设计

    前言 本来是想把整个dubbo源码解析一次性弄完,再做成一个系列来发布的,但是正巧最近有位好朋友要去杭州面试,就和我交流了一下.本着对dubbo源码略有心得的心态,在交流过程中也发表了个人的一些粗劣的 ...

  9. dubbo(5) Dubbo源码解析之服务调用过程

    来源:https://juejin.im/post/5ca4a1286fb9a05e731fc042 Dubbo源码解析之服务调用过程 简介 在前面的文章中,我们分析了 Dubbo SPI.服务导出与 ...

最新文章

  1. 学习Windows2008——设计活动目录
  2. jQuery实现表格拖动排序
  3. 【Android 逆向】使用 Python 代码解析 ELF 文件 ( PyCharm 中进行断点调试 | ELFFile 实例对象分析 )
  4. 【Flutter】Flutter 混合开发 ( Flutter 与 Native 通信 | Android 端实现 BasicMessageChannel 通信 )
  5. 评分卡建模—拒绝推断
  6. poj 1298 The Hardest Problem Ever
  7. 操作系统概念学习笔记 16 内存管理(二) 段页
  8. 查看JupyterNotebook的kernel及存放位置
  9. 我大学期间看的好书推荐
  10. 5-35 有理数均值 (20分)
  11. too many connections的一个实践
  12. javascript设计模式-抽象工厂模式
  13. 【转】VC动态内存分配PPT
  14. 设计一个媒体类,其中包含:书,CD及磁带3个子类。按照类的设计模式,完成他们的插入、删除和查找功能。
  15. Spark机器学习之协同过滤算法
  16. 【机器学习系列】GMM第二讲:高斯混合模型Learning问题,最大似然估计 or EM算法?
  17. 【设计模式】适配器模式
  18. java p12证书,如何使用已安装的.p12 证书在 Mac OS X 上签名 jar?
  19. 怎么将多个文本文件合并为一个文本文件
  20. Android MessageQueue与Message详解

热门文章

  1. Wallpaper Changer
  2. 华汇超市二层的小餐馆可当MBA案例了
  3. Vue实现swiper轮播
  4. Danger Scavenger 《致命游民复仇者》 for Mac v2.0.3 中文版 好玩的赛博朋克动作游戏
  5. Mind quantum 基础知识学习笔记(1)
  6. undo_retentionguarantee
  7. 【ASP.NET】System.Threading.ThreadAbortException中第一次偶然出现的“mscorlib.dll”类型的异常
  8. 利用Java计算多少次纸才能对折出珠峰高度
  9. 远程桌面工具栏无法唤出-退出办法 远程桌面关机
  10. 【已解决】无法连接Ubuntu下的TeamViewer或Ubuntu下TeamViewer连接未就绪等问题