版本
- spring-cloud-nacos-config 2021.0.5.0
- spring-alibaba-cloud 2021.0.5.0
- spring-boot 2.7.14
配置
application.yml
spring:
application:
name: wf-activity-web
config:
# ?refreshEnabled=true
import:
- optional:nacos:web.yml
nacos配置
比如启动给的时候配置文件是空的,后续在nacos管理后台新增或者修改 x: 100 此时会触发EnvironmentChangeEvent 事件。
x: 100
源码解析
nacos 客户端 在启动时候 启动一个异步任务 定时调度com.alibaba.nacos.client.config.impl.ClientWorker.ConfigRpcTransportClient#startInternal
@Override
public void startInternal() {
executor.schedule(() -> {
while (!executor.isShutdown() && !executor.isTerminated()) {
try {
listenExecutebell.poll(5L, TimeUnit.SECONDS);
if (executor.isShutdown() || executor.isTerminated()) {
continue;
}
// 核心逻辑
executeConfigListen();
} catch (Throwable e) {
LOGGER.error("[ rpc listen execute ] [rpc listen] exception", e);
}
}
}, 0L, TimeUnit.MILLISECONDS);
}
如果数据 md5变化就推送事件
com.alibaba.cloud.nacos.refresh.NacosContextRefresher#registerNacosListener
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();
nacosRefreshHistory.addRefreshRecord(dataId, group, configInfo);
// 发送 刷新时间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 {
configService.addListener(dataKey, groupKey, listener);
log.info("[Nacos Config] Listening config: dataId={}, group={}", dataKey,
groupKey);
}
catch (NacosException e) {
log.warn(String.format(
"register fail for nacos listener ,dataId=[%s],group=[%s]", dataKey,
groupKey), e);
}
}
这个时候 发送了一个org.springframework.cloud.endpoint.event.RefreshEvent 事件,这个时候找下消费者
发现 org.springframework.cloud.endpoint.event.RefreshEventListener#onApplicationEvent消费了
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ApplicationReadyEvent) {
handle((ApplicationReadyEvent) event);
}
else if (event instanceof RefreshEvent) {
// 刷新事件
handle((RefreshEvent) event);
}
}
进入handle事件
public void handle(RefreshEvent event) {
// this.ready.get() 这个是在 spring ready 的时候发送的事件改成true 默认false,
if (this.ready.get()) { // don't handle events before app is ready
log.debug("Event received " + event.getEventDesc());
Set<String> keys = this.refresh.refresh();
log.info("Refresh keys changed: " + keys);
}
}
进入 refresh方法
org.springframework.cloud.context.refresh.ContextRefresher#refresh
public synchronized Set<String> refresh() {
Set<String> keys = refreshEnvironment();
this.scope.refreshAll();
return keys;
}
进入 refreshEnvironment 方法
public synchronized Set<String> refresh() {
Set<String> keys = refreshEnvironment();
this.scope.refreshAll();
return keys;
}
public synchronized Set<String> refreshEnvironment() {
Map<String, Object> before = extract(this.context.getEnvironment().getPropertySources());
updateEnvironment();
Set<String> keys = changes(before, extract(this.context.getEnvironment().getPropertySources())).keySet();
//发送 EnvironmentChangeEvent 事件
this.context.publishEvent(new EnvironmentChangeEvent(this.context, keys));
return keys;
}
这个时候如果想监听nacos 配置变化 加一个EnvironmentChangeEvent 监听器即可