Dubbo源码-01-Config

一 类图

二 field

必赋值的域

ApplicationConfig ModuleConfig RegistryConfig ProtocolConfig MethodConfig ProviderConfig
name

三 AbstractConfig

1 appendParameters

// ApplicationConfigTest.java
@Test
    public void testParameters() throws Exception {
        ApplicationConfig application = new ApplicationConfig("app");
        application.setQosAcceptForeignIp(true);
        Map<String, String> parameters = new HashMap<String, String>();
        parameters.put("k1", "v1");
        ApplicationConfig.appendParameters(parameters, application);
        String s = parameters.toString();
        assertThat(parameters, hasEntry("k1", "v1"));
        assertThat(parameters, hasEntry(Constants.ACCEPT_FOREIGN_IP, "true"));
    }

hash表中键值对

{application=app, k1=v1, qos.accept.foreign.ip=true}
// AbstractConfig.java
protected static void appendParameters(Map<String, String> parameters, Object config) { // config中配置信息放到map中
        appendParameters(parameters, config, null);
    }

    /**
     * config中所有field做key 属性值做value
     *     - key通过field上注解自定义指定
     *     - key使用field名称
     * prefix是key前缀
     * 配置信息全部取出来放到哈希表中
     */
    @SuppressWarnings("unchecked")
    protected static void appendParameters(Map<String, String> parameters, Object config, String prefix) {
        if (config == null) {
            return;
        }
        Method[] methods = config.getClass().getMethods();
        for (Method method : methods) {
            try {
                String name = method.getName();
                /**
                 * getter方法
                 *     - getxxx
                 *     - isxxx
                 */
                if ((name.startsWith("get") || name.startsWith("is"))
                        && !"getClass".equals(name)
                        && Modifier.isPublic(method.getModifiers())
                        && method.getParameterTypes().length == 0
                        && isPrimitive(method.getReturnType())) {
                    // 每个域上面通过自定义注解定义了field映射的key
                    Parameter parameter = method.getAnnotation(Parameter.class);
                    if (method.getReturnType() == Object.class || parameter != null && parameter.excluded()) {
                        continue;
                    }
                    int i = name.startsWith("get") ? 3 : 2;
                    // 域field名称
                    String prop = StringUtils.camelToSplitName(name.substring(i, i + 1).toLowerCase() + name.substring(i + 1), ".");
                    String key;
                    // 有注解指定用注解 没注解指定用field名称
                    if (parameter != null && parameter.key().length() > 0) {
                        key = parameter.key();
                    } else {
                        key = prop;
                    }
                    Object value = method.invoke(config); // getter()方法执行结果
                    String str = String.valueOf(value).trim();
                    if (value != null && str.length() > 0) {
                        if (parameter != null && parameter.escaped()) {
                            str = URL.encode(str);
                        }
                        if (parameter != null && parameter.append()) {
                            String pre = parameters.get(Constants.DEFAULT_KEY + "." + key);
                            if (pre != null && pre.length() > 0) {
                                str = pre + "," + str;
                            }
                            pre = parameters.get(key);
                            if (pre != null && pre.length() > 0) {
                                str = pre + "," + str;
                            }
                        }
                        if (prefix != null && prefix.length() > 0) {
                            key = prefix + "." + key;
                        }
                        parameters.put(key, str);
                    } else if (parameter != null && parameter.required()) { // 某些Config中的field不能为空 ApplicationConfig和ModuleConfig中的name不能为空
                        throw new IllegalStateException(config.getClass().getSimpleName() + "." + key + " == null");
                    }
                } else if ("getParameters".equals(name)
                        && Modifier.isPublic(method.getModifiers())
                        && method.getParameterTypes().length == 0
                        && method.getReturnType() == Map.class) {
                    Map<String, String> map = (Map<String, String>) method.invoke(config, new Object[0]);
                    if (map != null && map.size() > 0) {
                        String pre = (prefix != null && prefix.length() > 0 ? prefix + "." : "");
                        for (Map.Entry<String, String> entry : map.entrySet()) {
                            parameters.put(pre + entry.getKey().replace('-', '.'), entry.getValue());
                        }
                    }
                }
            } catch (Exception e) {
                throw new IllegalStateException(e.getMessage(), e);
            }
        }
    }

2 appendProperties

// ProviderConfigTest.java
@Test
    public void test00() {
        ProviderConfig cfg = new ProviderConfig();
        ProviderConfig.appendProperties(cfg);
        Map<String, String> m = new HashMap<>();
        ProviderConfig.appendParameters(m, cfg);
        System.out.println(m.toString());
    }
// AbstractConfig.java
/**
     * 为Config的field到VM参数中找是否配置过值写回到Config中
     *     - ProviderConfig->dubbo.provider.xxx
     */
    protected static void appendProperties(AbstractConfig config) {
        if (config == null) return; // 要从配置类实例中获取对应的配置项
        /**
         * 配置项名称
         *     - dubbo.provider.
         *     - dubbo.application.
         *     - dubbo.consumer.
         */
        String prefix = "dubbo." + getTagName(config.getClass()) + ".";
        Method[] methods = config.getClass().getMethods();
        for (Method method : methods) {
            try {
                String name = method.getName();
                // setter方法
                if (name.length() > 3
                        && name.startsWith("set")
                        && Modifier.isPublic(method.getModifiers())
                        && method.getParameterTypes().length == 1
                        && isPrimitive(method.getParameterTypes()[0])
                ) {
                    // field名称
                    String property = StringUtils.camelToSplitName(name.substring(3, 4).toLowerCase() + name.substring(4), ".");

                    String value = null;
                    if (config.getId() != null && config.getId().length() > 0) {
                        String pn = prefix + config.getId() + "." + property; // field映射的配置名称
                        value = System.getProperty(pn); // field映射的配置值
                        if (!StringUtils.isBlank(value)) {
                            logger.info("Use System Property " + pn + " to config dubbo");
                        }
                    }
                    if (value == null || value.length() == 0) {
                        String pn = prefix + property; // field映射的配置名称
                        value = System.getProperty(pn); // field映射的配置值
                        if (!StringUtils.isBlank(value)) {
                            logger.info("Use System Property " + pn + " to config dubbo");
                        }
                    }
                    if (value == null || value.length() == 0) {
                        Method getter;
                        try {
                            // field的getter方法
                            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) {
                                if (config.getId() != null && config.getId().length() > 0) {
                                    value = ConfigUtils.getProperty(prefix + config.getId() + "." + property);
                                }
                                if (value == null || value.length() == 0) {
                                    value = ConfigUtils.getProperty(prefix + property);
                                }
                                if (value == null || value.length() == 0) {
                                    String legacyKey = legacyProperties.get(prefix + property);
                                    if (legacyKey != null && legacyKey.length() > 0) {
                                        value = convertLegacyValue(legacyKey, ConfigUtils.getProperty(legacyKey));
                                    }
                                }

                            }
                        }
                    }
                    // field根据映射规则作为配置key到VM参数中找是否配置过值 写到Config中
                    if (value != null && value.length() > 0) {
                        method.invoke(config, convertPrimitive(method.getParameterTypes()[0], value));
                    }
                }
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }
        }
    }
posted @   Bannirui  阅读(75)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示