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);
}
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?