spring cloud bus 源码 - 动态刷新
刷新入口
spring cloud bus 提供了两个刷新的配置入口, RefreshBusEndpoint
:
@Endpoint(id = "busrefresh") // TODO: document new id
public class RefreshBusEndpoint extends AbstractBusEndpoint {
public RefreshBusEndpoint(ApplicationEventPublisher publisher, String id,
Destination.Factory destinationFactory) {
super(publisher, id, destinationFactory);
}
@WriteOperation
public void busRefreshWithDestination(@Selector(match = Match.ALL_REMAINING) String[] destinations) {
String destination = StringUtils.arrayToDelimitedString(destinations, ":");
publish(new RefreshRemoteApplicationEvent(this, getInstanceId(), getDestination(destination)));
}
@WriteOperation
public void busRefresh() {
publish(new RefreshRemoteApplicationEvent(this, getInstanceId(), getDestination(null)));
}
}
你可以这样访问: /actuator/busrefres
/actuator/busrefresh/customers:9000
/actuator/busrefresh/customers:**
然后由 RefreshListener
监听事件:
public class RefreshListener implements ApplicationListener<RefreshRemoteApplicationEvent> {
private static Log log = LogFactory.getLog(RefreshListener.class);
private ContextRefresher contextRefresher;
private ServiceMatcher serviceMatcher;
public RefreshListener(ContextRefresher contextRefresher, ServiceMatcher serviceMatcher) {
this.contextRefresher = contextRefresher;
this.serviceMatcher = serviceMatcher;
}
@Override
public void onApplicationEvent(RefreshRemoteApplicationEvent event) {
log.info("Received remote refresh request.");
if (serviceMatcher.isForSelf(event)) {
Set<String> keys = this.contextRefresher.refresh();
log.info("Keys refreshed " + keys);
}
else {
log.info("Refresh not performed, the event was targeting " + event.getDestinationService());
}
}
}
ContextRefresher
public abstract class ContextRefresher {
private RefreshScope scope;
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();
this.context.publishEvent(new EnvironmentChangeEvent(this.context, keys));
return keys;
}
}
这里做的就是几件事:
- 获取旧的环境配置
- 获取新的环境配置(如可以到配置中心拉取配置)
- 比对变化的 key
- 发布 EnvironmentChangeEvent 事件,通知 Evnironment 设置最新的value,
- 通知ConfigurationPropertiesRebinder 重新绑定
@ConfigurationProperties
注解的Bean RefreshScope.refreashAll()
, 销毁 scope 为refresh
的Bean 的集合
刷新流程: