springcloud提供了顶层接口PropertiesSourceLocator,所有基于Springcloud的微服务组件都需要按照springcloud的规范实现,nacos也不列外,nacos的实现是NacosPropertySourceLocator。
NacosPropertySourceLocator根据springboot的自动转配会被加载到ioc环境中,且在
org.springframework.cloud.bootstrap.config.PropertySourceBootstrapConfiguration进行依赖注入时该类也会被填充到propertySourceLocators 字段中。
@Autowired(required = false)
List propertySourceLocators = new ArrayList<>();
接着在类PropertySourceBootstrapConfiguration进行初始化时会遍历propertySourceLocators字段进行locator.locateCollection(environment)调用。
最终会调用到com.alibaba.cloud.nacos.client.NacosPropertySourceLocator#locate方法
最终按顺序加载我们所配置的各种类型的配置文件
CompositePropertySource composite = new CompositePropertySource(
NACOS_PROPERTY_SOURCE_NAME)
##共享类型配置文件
loadSharedConfiguration(composite);
##扩展类型配置文件
loadExtConfiguration(composite);
##应用类型配置文件
loadApplicationConfiguration(composite, dataIdPrefix, nacosConfigProperties, env);
装置配置文件代码如下:
NacosPropertySource propertySource = this.loadNacosPropertySource(dataId, group,
fileExtension, isRefreshable);
this.addFirstPropertySource(composite, propertySource, false);
private void addFirstPropertySource(final CompositePropertySource composite,
NacosPropertySource nacosPropertySource, boolean ignoreEmpty) {
if (null == nacosPropertySource || null == composite) {
return;
}
if (ignoreEmpty && nacosPropertySource.getSource().isEmpty()) {
return;
}
composite.addFirstPropertySource(nacosPropertySource);
}
public void addFirstPropertySource(PropertySource> propertySource) {
List> existing = new ArrayList<>(this.propertySources);
this.propertySources.clear();
this.propertySources.add(propertySource);
this.propertySources.addAll(existing);
}
可以通过下面这段代码发现加载完侯会将配置文件放在composite中的第一个元素,当应用程序
加载Environment中的属性值时,当匹配到第一个值时就会返回,即使后面有相同元素的值也不再加载(不了解的可以去看一下@Value的工作机制),由此可见nacos配置文件的优先级应该是
application>ext>share
接下来我们看loadApplicationConfiguration(composite, dataIdPrefix, nacosConfigProperties, env);
是如何加载的通常情况下dataIdPrefix就是我们配置的spring.application.name
private void loadApplicationConfiguration(
CompositePropertySource compositePropertySource, String dataIdPrefix,
NacosConfigProperties properties, Environment environment) {
String fileExtension = properties.getFileExtension();
String nacosGroup = properties.getGroup();
// load directly once by default
loadNacosDataIfPresent(compositePropertySource, dataIdPrefix, nacosGroup,
fileExtension, true);
// load with suffix, which have a higher priority than the default
loadNacosDataIfPresent(compositePropertySource,
dataIdPrefix + DOT + fileExtension, nacosGroup, fileExtension, true);
// Loaded with profile, which have a higher priority than the suffix
for (String profile : environment.getActiveProfiles()) {
String dataId = dataIdPrefix + SEP1 + profile + DOT + fileExtension;
loadNacosDataIfPresent(compositePropertySource, dataId, nacosGroup,
fileExtension, true);
}
}
通过代码可以看到按照顺寻从上往下加载的分别是,dataIdPrefix,dataIdPrefix.fileExtension,
dataIdPrefix.profile.fileExtension。所以该文件的优先级为dataIdPrefix.profile.fileExtension>dataIdPrefix.fileExtension>dataIdPrefix,掌握了这些后,我们在读取配置文件时就不会出现明明配置的是这个属性为什么变成其它了,此时您就需要思考一下是不是被别的配置文件覆盖了,别的配置文件优先级是否比你高。