背景
目前apollo官方實現@ConfigurationProperties需要配合使用EnvironmentChangeEvent或RefreshScope(需要引入springCloud-context),考慮一種簡單的實現方式如下:
思路
監聽apollo配置刷新事件,然后通過spring的工具類獲取當前配置類的bean實例對象(單例),通過反射將對應改變的配置項注入配置類bean實例。
代碼實現
@Data
@Slf4j
@Configuration
@ConfigurationProperties
@EnableApolloConfig
public class AppConfig {
private Map<String, String> xxConfigMap;
@ApolloConfigChangeListener
public void onChange(ConfigChangeEvent changeEvent) {
//this.applicationContext.publishEvent(new EnvironmentChangeEvent(changeEvent.changedKeys()));
changeEvent.changedKeys().stream().map(changeEvent::getChange).forEach(change -> {
log.info("Found change - key: {}, oldValue: {}, newValue: {}, changeType: {}", change.getPropertyName(), change.getOldValue(), change.getNewValue(), change.getChangeType());
String vKey = change.getPropertyName();
String newValue = change.getNewValue();
if (vKey.contains(".")) {
//取出對應的field 反射重新賦值
AppConfig appConfig = SpringContext.getBean(AppConfig.class);
try {
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(vKey.substring(0, vKey.indexOf(".")), appConfig.getClass());
Map<String, String> map = (Map<String, String>) propertyDescriptor.getReadMethod().invoke(appConfig);
map.put(vKey.substring(vKey.indexOf(".")+1,vKey.length()), newValue);
propertyDescriptor.getWriteMethod().invoke(appConfig, map);
} catch (Exception e) {
log.error("replace field {} error", vKey);
}
}
});
}
//測試是否生效
@PostConstruct
void test() {
Executors.newSingleThreadExecutor().submit(() -> {
while (true) {
log.info(xxConfigMap.toString());
Thread.sleep(2000);
}
});
}
}