本文基于nacos-2.0.3版本
nacos中,每一个@NacosPropertySource都被解析为一个PropertySource对象,并且将该对象添加到Environment的propertySources集合中,这个集合是List对象,默认每新增一个PropertySource对象,都会将其添加到集合的末尾,我们可以通过NacosPropertySource中的first、before等属性设置它们的顺序。
所有的@NacosPropertySource解析完毕后,下面开始解析@NacosValue。nacos使用如下代码获得NacosValue中指定的配置值:
//environment即是spring的Environment对象
String key = environment.resolvePlaceholders(entry.getKey());
String newValue = environment.getProperty(key);
从上面代码可以知道,如果在多个PropertySource对象中有相同的配置,那么谁在PropertySource集合中排序靠前,就会采用谁的配置。
如果对象属性采用了第一个PropertySource的配置,此时具有相同配置的第二个PropertySource发生变化,那么是否会更新该属性?
答案是否,我们先来看一下nacos收到配置更新后如何更新对象属性值的。
当服务端有配置更新时,都会调用onApplicationEvent()方法:
public void onApplicationEvent(NacosConfigReceivedEvent event) {
// In to this event receiver, the environment has been updated the
// latest configuration information, pull directly from the environment
// fix issue #142
//遍历需要自动刷新的配置
for (Map.Entry<String, List<NacosValueTarget>> entry : placeholderNacosValueTargetMap
.entrySet()) {
String key = environment.resolvePlaceholders(entry.getKey());
//根据配置的key从environment对象中获取值
String newValue = environment.getProperty(key);
if (newValue == null) {
continue;
}
List<NacosValueTarget> beanPropertyList = entry.getValue();
for (NacosValueTarget target : beanPropertyList) {
String md5String = MD5Utils.md5Hex(newValue, "UTF-8");
//比较更改前后值是否相同
boolean isUpdate = !target.lastMD5.equals(md5String);
if (isUpdate) {
target.updateLastMD5(md5String);
Object evaluatedValue = resolveNotifyValue(target.nacosValueExpr, key, newValue);
if (target.method == null) {
setField(target, evaluatedValue);//更新属性
}
else {
setMethod(target, evaluatedValue);//调用方法更新配置
}
}
}
}
}
从上面代码可以看到,每次都是根据environment.getProperty(key)
获取最新的配置值,所以排序在后面的PropertySource是不会访问到的,每次都是访问第一个PropertySource对象,只要第一个不改,对象属性值永远不会发生变化。