spring cloud动态刷新nacos配置,是通过spring boot自带的@RefreshScope注解来实现的,在类上面加上这个注解,就能动态刷新配置了。实现过程是通过添加listener,来监听nacos配置,当有配置修改时,会发送RefreshEvent事件,带有@RefreshScope注解的类就能自动刷新配置了。listener监听配置变化具体原理可参考下篇文章:客户端监听机制
NacosConfigAutoConfiguration会自动注入NacosContextRefresher和NacosRefreshHistory两个bean。NacosContextRefresher会执行动态刷新具体逻辑,NacosRefreshHistory会记录配置刷新历史。
NacosContextRefresher监听ApplicationReadyEvent事件,当spring application就绪之后,就会启动对nacos配置的监听,代码如下:
@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
//如果没有初始化,就添加nacos监听
if (this.ready.compareAndSet(false, true)) {
this.registerNacosListenersForApplications();
}
}
private void registerNacosListenersForApplications() {
if (isRefreshEnabled()) {
//从本地缓存中取出配置列表遍历
for (NacosPropertySource propertySource : NacosPropertySourceRepository
.getAll()) {
if (!propertySource.isRefreshable()) {
continue;
}
String dataId = propertySource.getDataId();
//注册listener
registerNacosListener(propertySource.getGroup(), dataId);
}
}
}
private void registerNacosListener(final String groupKey, final String dataKey) {
String key = NacosPropertySourceRepository.getMapKey(dataKey, groupKey);
Listener listener = listenerMap.computeIfAbsent(key,
lst -> new AbstractSharedListener() {
@Override
public void innerReceive(String dataId, String group,
String configInfo) {
//累计刷新次数
refreshCountIncrement();
//添加历史记录,用于在end point中展示
nacosRefreshHistory.addRefreshRecord(dataId, group, configInfo);
// todo feature: support single refresh for listening
//发布RefreshEvent事件
applicationContext.publishEvent(
new RefreshEvent(this, null, "Refresh Nacos config"));
if (log.isDebugEnabled()) {
log.debug(String.format(
"Refresh Nacos config group=%s,dataId=%s,configInfo=%s",
group, dataId, configInfo));
}
}
});
try {
//添加listener
configService.addListener(dataKey, groupKey, listener);
}
catch (NacosException e) {
log.warn(String.format(
"register fail for nacos listener ,dataId=[%s],group=[%s]", dataKey,
groupKey), e);
}
}