微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Dubbo七: 属性配置

1. 概述

首先,我们来看看属性配置的定义:

FROM 《Dubbo 用户指南 —— 属性配置》

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

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

从定义上,很关键的一个词是 “简单” 。

OK ,下面在开始看看具体代码之前,胖友先仔细阅读下 《Dubbo 用户指南 —— 属性配置》 ,有助于下面代码的理解。

2. AbstractConfig

在 AbstractConfig 中,提供了 #appendProperties(config) 方法,读取启动参数变量和 properties 配置到配置对象。在前面的几篇文章里,我们多次看到这个方法调用,如下图所示:

读取调用

代码如下:

 1: protected static void appendProperties(AbstractConfig config) {
 2:     if (config == null) {
 3:         return;
 4:     }
 5:     String prefix = "dubbo." + getTagName(config.getClass()) + ".";
 6:     Method[] methods = config.getClass().getmethods();
 7:     for (Method method : methods) {
 8:         try {
 9:             String name = method.getName();
10:             if (name.length() > 3 && name.startsWith("set") && Modifier.isPublic(method.getModifiers()) // 方法是 public 的 setting 方法。
11:                     && method.getParameterTypes().length == 1 && isPrimitive(method.getParameterTypes()[0])) { // 方法的唯一参数是基本数据类型
12:                 // 获得属性名,例如 `ApplicationConfig#setName(...)` 方法,对应的属性名为 name 。
13:                 String property = StringUtils.camelToSplitName(name.substring(3, 4).toLowerCase() + name.substring(4), ".");
14: 
15:                 // 【启动参数变量】优先从带有 `Config#id` 的配置中获取,例如:`dubbo.application.demo-provider.name` 。
16:                 String value = null;
17:                 if (config.getId() != null && config.getId().length() > 0) {
18:                     String pn = prefix + config.getId() + "." + property; // 带有 `Config#id`
19:                     value = System.getProperty(pn);
20:                     if (!StringUtils.isBlank(value)) {
21:                         logger.info("Use System Property " + pn + " to config dubbo");
22:                     }
23:                 }
24:                 // 【启动参数变量】获取不到,其次不带 `Config#id` 的配置中获取,例如:`dubbo.application.name` 。
25:                 if (value == null || value.length() == 0) {
26:                     String pn = prefix + property; // // 不带 `Config#id`
27:                     value = System.getProperty(pn);
28:                     if (!StringUtils.isBlank(value)) {
29:                         logger.info("Use System Property " + pn + " to config dubbo");
30:                     }
31:                 }
32:                 if (value == null || value.length() == 0) {
33:                     // 覆盖优先级为:启动参数变量 > XML 配置 > properties 配置,因此需要使用 getter 判断 XML 是否已经设置
34:                     Method getter;
35:                     try {
36:                         getter = config.getClass().getmethod("get" + name.substring(3), new Class<?>[0]);
37:                     } catch (NoSuchMethodException e) {
38:                         try {
39:                             getter = config.getClass().getmethod("is" + name.substring(3), new Class<?>[0]);
40:                         } catch (NoSuchMethodException e2) {
41:                             getter = null;
42:                         }
43:                     }
44:                     if (getter != null) {
45:                         if (getter.invoke(config, new Object[0]) == null) { // 使用 getter 判断 XML 是否已经设置
46:                             // 【properties 配置】优先从带有 `Config#id` 的配置中获取,例如:`dubbo.application.demo-provider.name` 。
47:                             if (config.getId() != null && config.getId().length() > 0) {
48:                                 value = ConfigUtils.getProperty(prefix + config.getId() + "." + property);
49:                             }
50:                             // 【properties 配置】获取不到,其次不带 `Config#id` 的配置中获取,例如:`dubbo.application.name` 。
51:                             if (value == null || value.length() == 0) {
52:                                 value = ConfigUtils.getProperty(prefix + property);
53:                             }
54:                             // 【properties 配置】老版本兼容,获取不到,最后不带 `Config#id` 的配置中获取,例如:`dubbo.protocol.name` 。
55:                             if (value == null || value.length() == 0) {
56:                                 String legacyKey = legacyProperties.get(prefix + property);
57:                                 if (legacyKey != null && legacyKey.length() > 0) {
58:                                     value = convertLegacyValue(legacyKey, ConfigUtils.getProperty(legacyKey));
59:                                 }
60:                             }
61: 
62:                         }
63:                     }
64:                 }
65:                 // 获取到值,进行反射设置。
66:                 if (value != null && value.length() > 0) {
67:                     method.invoke(config, new Object[]{convertPrimitive(method.getParameterTypes()[0], value)});
68:                 }
69:             }
70:         } catch (Exception e) {
71:             logger.error(e.getMessage(), e);
72:         }
73:     }
74: }
  • 第 5 行:获得配置项前缀。此处的 #getTagName(Class<?>) 方法,使用配置类的类名,获得对应的属性标签。该方法代码如下:

     1: /**
     2:  * 配置类名的后缀
     3:  * 例如,ServiceConfig 后缀为 Config;ServiceBean 后缀为 Bean。
     4:  */
     5: private static final String[] SUFFIXES = new String[]{"Config", "Bean"};
     6: 
     7: /**
     8:  * 获取类名对应的属性标签,例如,ServiceConfig 对应为 service 。
     9:  *
    10:  * @param cls 类名
    11:  * @return 标签
    12:  */
    13: private static String getTagName(Class<?> cls) {
    14:     String tag = cls.getSimpleName();
    15:     for (String suffix : SUFFIXES) {
    16:         if (tag.endsWith(suffix)) {
    17:             tag = tag.substring(0, tag.length() - suffix.length());
    18:             break;
    19:         }
    20:     }
    21:     tag = tag.toLowerCase();
    22:     return tag;
    23: }
    
  • 第 6 行:获得配置类的所有方法,用于下面通过反射获得配置项的属性名,再用属性名,去读取启动参数变量和 properties 配置到配置对象。

  • 第 10 至 11 行:public && setting 方法 && 唯一参数为基本类型。

  • 第 13 行:获得属性名。例如,ApplicationConfig#setName(...) 方法,对应的属性名为 "name" 。

  • 读取的覆盖策略如下:

    覆盖策略

  • 第 15 至 31 行:优先从【启动参数变量获取配置项的值。

    • 版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐