我使用的是nacos配置中心。其实这里的动态路由大部分就是nacos的原理了。
1、nacos注册监听NacosConfigAutoConfiguration中初始化了一个bean,nacosContextRefresher。
public class NacosContextRefresher
implements ApplicationListener, ApplicationContextAware {
它 本身监听readyEvent,当启动完成后
@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
// many Spring context
if (this.ready.compareAndSet(false, true)) {
this.registerNacosListenersForApplications();
}
}
进行注册nacos的监听器,我们直接跟踪到最底层方法:
private void registerNacosListener(final String groupKey, final String dataKey) {
//group和dataid 组成新的key
String key = NacosPropertySourceRepository.getMapKey(dataKey, groupKey);
//listener监听器map 注册监听器
Listener listener = listenerMap.computeIfAbsent(key,
lst -> new AbstractSharedListener() {
@Override
public void innerReceive(String dataId, String group,
String configInfo) {
//原子计数器,后面nacos专题讲做什么的
refreshCountIncrement();
//新增刷新记录
nacosRefreshHistory.addRefreshRecord(dataId, group, configInfo);
// 发布 RefreshEvent,这个是spring cloud context 公共的事件,不止
//nacos
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 {
//listner和key 进行绑定,这样就能哪个配置文件刷新时,执行哪个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);
}
}
2、发布事件
当我们点击nacos配置中心的 配置文件发布按钮后,就会执行到上图里的监听器里。会发布一个spring cloud context的refreshEvent,org.springframework.cloud.endpoint.event.RefreshEventListener会监听到事件并最终又会调用org.springframework.cloud.context.scope.refresh.RefreshScope#refreshAll方法
@ManagedOperation(description = "Dispose of the current instance of all beans "
+ "in this scope and force a refresh on next method execution.")
public void refreshAll() {
super.destroy();
this.context.publishEvent(new RefreshScopeRefreshedEvent());
}
这里看到又发布了一个RefreshScopeRefreshedEvent事件。而之前我们看过RouteRefreshListener的,我们看看它监听哪些事件怎么处理的
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ContextRefreshedEvent) {
ContextRefreshedEvent refreshedEvent = (ContextRefreshedEvent) event;
if (!WebServerApplicationContext.hasServerNamespace(refreshedEvent.getApplicationContext(), "management")) {
reset();
}
}
else if (event instanceof RefreshScopeRefreshedEvent || event instanceof InstanceRegisteredEvent) {
reset();
}
else if (event instanceof ParentHeartbeatEvent) {
ParentHeartbeatEvent e = (ParentHeartbeatEvent) event;
resetIfNeeded(e.getValue());
}
else if (event instanceof HeartbeatEvent) {
HeartbeatEvent e = (HeartbeatEvent) event;
resetIfNeeded(e.getValue());
}
}
我们看到它监听了所有的事件,但是它内部有区分事件处理,正好也有 RefreshScopeRefreshedEvent事件,因此 会重新触发重加载route的请求。至于properties为什么会改变,看nacos时再说



