在使用springckoud config的时候,修改了配置,是需要调用/actuator/refresh来刷新客户端的配置
@Endpoint(id = "refresh")
public class RefreshEndpoint {
...
@WriteOperation
public Collection<String> refresh() {
Set<String> keys = this.contextRefresher.refresh();
return keys;
}
}
当我们调用/actuator/refresh的时候会调用到org.springframework.cloud.endpoint.RefreshEndpoint#refresh
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());
addConfigFilesToEnvironment();
Set<String> keys = changes(before,
extract(this.context.getEnvironment().getPropertySources())).keySet();
this.context.publishEvent(new EnvironmentChangeEvent(this.context, keys));
return keys;
}
可以看到refresh 方法中加上了synchronized,解决并发问题
调用refreshEnvironment方法后对
refreshEnvironment方法中
1.获取了当前环境中未更新前的的环境变量
2.将更新后的环境变量添加到Environment中
3.获取更新的环境变量
4.发布EnvironmentChangeEvent事件
public void rebind() {
this.errors.clear();
for (String name : this.beans.getBeanNames()) {
rebind(name);
}
}
@ManagedOperation
public boolean rebind(String name) {
if (!this.beans.getBeanNames().contains(name)) {
return false;
}
if (this.applicationContext != null) {
Object bean = this.applicationContext.getBean(name);
if (AopUtils.isAopProxy(bean)) {
bean = ProxyUtils.getTargetObject(bean);
}
if (bean != null) {
this.applicationContext.getAutowireCapableBeanFactory()
.destroyBean(bean);
this.applicationContext.getAutowireCapableBeanFactory()
.initializeBean(bean, name);
return true;
}
}
return false;
}
ConfigurationPropertiesRebinder是一个ApplicationListener,用于相应上述的EnvironmentChangeEvent事件,其核心方法就是上面的rebind方法
这里,就是对 beans这个集合里面的bean先进行销毁,然后再重新初始化就,那再重新初始化的时候就会去Environment中拿到最新的值,所以就完成了配置的刷新
而beans 这个集合里面的内容就是标注@ConfigurationProperties 的bean