feat(clients): 各客户端支持环境变量配置,Spring Boot 2 客户端优化选择性刷新
- Dockerfile.springboot2: 更换基础镜像为阿里云私有镜像 - .NET/SpringBoot2 demo: 配置项改为从环境变量读取,支持 Docker 传参 - Spring Boot 2 客户端: @Value/@ConfigurationProperties 刷新优化为只刷新受变更 key 影响的字段 - README_DOCKERFILE.md: 标注 .NET 客户端 Docker 测试通过
This commit is contained in:
+8
-6
@@ -333,6 +333,8 @@ public class ConfigcenterContext {
|
||||
result = LocalCacheUtils.read();
|
||||
} else {
|
||||
LocalCacheUtils.write(result);
|
||||
int configCount = result.size();
|
||||
logger.info("[ConfigClient] fetched {} configs", configCount);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -410,7 +412,7 @@ public class ConfigcenterContext {
|
||||
|
||||
// Refresh @Value and @ConfigurationProperties fields
|
||||
logger.info("[RefreshScope] Calling refreshDynamicConfigFields()...");
|
||||
refreshDynamicConfigFields();
|
||||
refreshDynamicConfigFields(updateConfig.keySet());
|
||||
logger.info("[RefreshScope] refreshDynamicConfigFields() completed");
|
||||
}
|
||||
}
|
||||
@@ -448,13 +450,13 @@ public class ConfigcenterContext {
|
||||
}
|
||||
}
|
||||
// Refresh @Value and @ConfigurationProperties fields
|
||||
refreshDynamicConfigFields();
|
||||
refreshDynamicConfigFields(new HashSet<>(keys));
|
||||
}
|
||||
|
||||
private void refreshDynamicConfigFields() {
|
||||
private void refreshDynamicConfigFields(Set<String> changedKeys) {
|
||||
if (applicationContext != null) {
|
||||
try {
|
||||
logger.info("[RefreshScope] Starting dynamic config field refresh...");
|
||||
logger.info("[RefreshScope] Starting dynamic config field refresh for keys: {}", String.join(", ", changedKeys));
|
||||
StandardEnvironment env = (StandardEnvironment) applicationContext.getEnvironment();
|
||||
// 直接创建 RefreshScopeRegistry 并注册为 BeanPostProcessor
|
||||
RefreshScopeRegistry registry = new RefreshScopeRegistry(env);
|
||||
@@ -474,8 +476,8 @@ public class ConfigcenterContext {
|
||||
configPropsCount = registry.getConfigPropsCount();
|
||||
logger.info("[RefreshScope] Recorded {} @Value fields and {} @ConfigurationProperties beans", valueFieldCount, configPropsCount);
|
||||
|
||||
// 刷新
|
||||
registry.refresh();
|
||||
// 刷新(只刷新受影响的字段)
|
||||
registry.refresh(changedKeys);
|
||||
logger.info("[RefreshScope] RefreshScopeRegistry.refresh() completed, refreshed {} @Value fields and {} @ConfigurationProperties beans", registry.getValueFieldCount(), registry.getConfigPropsCount());
|
||||
} catch (Exception e) {
|
||||
logger.warn("[RefreshScope] RefreshScopeRegistry.refresh() error, msg:{}", e.getMessage(), e);
|
||||
|
||||
+4
-1
@@ -72,7 +72,10 @@ public class InternalConfigChangeListener {
|
||||
logger.info("[ConfigClient] {} configs deleted: {}", deletedKeys.length, String.join(", ", deletedKeys));
|
||||
}
|
||||
}
|
||||
if (!data.isEmpty()) context.updateConfig(data);
|
||||
if (!data.isEmpty()) {
|
||||
context.updateConfig(data);
|
||||
logger.info("[ConfigClient] {} configs changed: {}", data.size(), String.join(", ", data.keySet()));
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
||||
+24
-18
@@ -3,6 +3,7 @@ package cn.odboy.confcenter;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -60,27 +61,29 @@ public class RefreshScopeRegistry implements BeanPostProcessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh all @Value fields and @ConfigurationProperties beans
|
||||
* Refresh only @Value fields and @ConfigurationProperties beans that are affected by changed keys
|
||||
*/
|
||||
public void refresh() {
|
||||
refreshValueFields();
|
||||
refreshConfigPropsBeans();
|
||||
public void refresh(Set<String> changedKeys) {
|
||||
refreshValueFields(changedKeys);
|
||||
refreshConfigPropsBeans(changedKeys);
|
||||
}
|
||||
|
||||
private void refreshValueFields() {
|
||||
private void refreshValueFields(Set<String> changedKeys) {
|
||||
for (ValueFieldHolder holder : valueFields) {
|
||||
try {
|
||||
holder.refresh(environment);
|
||||
} catch (Exception e) {
|
||||
// ignore refresh errors
|
||||
if (changedKeys.contains(holder.key)) {
|
||||
try {
|
||||
holder.refresh(environment);
|
||||
} catch (Exception e) {
|
||||
// ignore refresh errors
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshConfigPropsBeans() {
|
||||
private void refreshConfigPropsBeans(Set<String> changedKeys) {
|
||||
for (ConfigPropsHolder holder : configPropsBeans) {
|
||||
try {
|
||||
holder.refresh(environment);
|
||||
holder.refresh(environment, changedKeys);
|
||||
} catch (Exception e) {
|
||||
// ignore refresh errors
|
||||
}
|
||||
@@ -149,24 +152,27 @@ public class RefreshScopeRegistry implements BeanPostProcessor {
|
||||
this.bean = bean;
|
||||
}
|
||||
|
||||
void refresh(Environment env) {
|
||||
void refresh(Environment env, Set<String> changedKeys) {
|
||||
Class<?> clazz = bean.getClass();
|
||||
ConfigurationProperties anno = clazz.getAnnotation(ConfigurationProperties.class);
|
||||
if (anno != null) {
|
||||
String prefix = anno.prefix();
|
||||
bindProperties(bean, prefix, env);
|
||||
bindProperties(bean, prefix, env, changedKeys);
|
||||
}
|
||||
}
|
||||
|
||||
private void bindProperties(Object bean, String prefix, Environment env) {
|
||||
private void bindProperties(Object bean, String prefix, Environment env, Set<String> changedKeys) {
|
||||
try {
|
||||
Class<?> clazz = bean.getClass();
|
||||
for (Field field : getAllDeclaredFields(clazz)) {
|
||||
String propertyName = prefix + "." + camelToKebab(field.getName());
|
||||
String value = env.getProperty(propertyName);
|
||||
if (value != null) {
|
||||
field.setAccessible(true);
|
||||
field.set(bean, convertType(field.getType(), value));
|
||||
// Only refresh if this property key is in changedKeys
|
||||
if (changedKeys.contains(propertyName)) {
|
||||
String value = env.getProperty(propertyName);
|
||||
if (value != null) {
|
||||
field.setAccessible(true);
|
||||
field.set(bean, convertType(field.getType(), value));
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
||||
Reference in New Issue
Block a user