依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
一.入口
1.通过spring.factories注入spring,NacosConfigBootstrapConfiguration
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(name = "spring.cloud.nacos.config.enabled", matchIfMissing = true)
public class NacosConfigBootstrapConfiguration {
@Bean
@ConditionalOnMissingBean
// 读取nacos相关配置
public NacosConfigProperties nacosConfigProperties() {
return new NacosConfigProperties();
}
@Bean
@ConditionalOnMissingBean
//实例化NacosConfigManager,创建ConfigService,ConfigService是配置读取更新的核心类
public NacosConfigManager nacosConfigManager(
NacosConfigProperties nacosConfigProperties) {
return new NacosConfigManager(nacosConfigProperties);
}
@Bean
//spring初始化时会调用NacosPropertySourceLocator.locate方法,
//nacos通过此方法加载nacos-server配置
public NacosPropertySourceLocator nacosPropertySourceLocator(
NacosConfigManager nacosConfigManager) {
return new NacosPropertySourceLocator(nacosConfigManager);
}
}
//NacosPropertySourceLocator.locate方法
//此处只研究loadApplicationConfiguration()加载应用配置,其余同理
//loadExtConfiguration()加载共享配置 shared-configs
//loadExtConfiguration()加载扩展配置 extension-configs
@Override
public PropertySource<?> locate(Environment env) {
........
loadSharedConfiguration(composite);
loadExtConfiguration(composite);
loadApplicationConfiguration(composite, dataIdPrefix, nacosConfigProperties, env);
return composite;
}
二.加载config配置
1.NacosPropertySourceLocator.loadApplicationConfiguration方法中调用加载配置方法loadNacosDataIfPresent(),
参数isRefreshable代表是否实时刷新
private void loadNacosDataIfPresent(final CompositePropertySource composite,
final String dataId, final String group, String fileExtension,
boolean isRefreshable) {
.........
//获取配置
NacosPropertySource propertySource = this.loadNacosPropertySource(dataId, group,
fileExtension, isRefreshable);
//将配置交给spring的propertySource管理,之后就可以通过Environment类获取具体配置了
this.addFirstPropertySource(composite, propertySource, false);
}
2.loadNacosPropertySource()方法
private NacosPropertySource loadNacosPropertySource(final String dataId,
final String group, String fileExtension, boolean isRefreshable) {
//如果不实时刷新,且已经刷新过了,则从本地缓存的Map里取
if (NacosContextRefresher.getRefreshCount() != 0) {
if (!isRefreshable) {
return NacosPropertySourceRepository.getNacosPropertySource(dataId,
group);
}
}
//获取配置
return nacosPropertySourceBuilder.build(dataId, group, fileExtension,
isRefreshable);
}
3.NacosPropertySourceBuilder.build()
NacosPropertySource build(String dataId, String group, String fileExtension,
boolean isRefreshable) {
//加载配置
Map<String, Object> p = loadNacosData(dataId, group, fileExtension);
NacosPropertySource nacosPropertySource = new NacosPropertySource(group, dataId,
p, new Date(), isRefreshable);
//将配置放到缓存Map
NacosPropertySourceRepository.collectNacosPropertySource(nacosPropertySource);
return nacosPropertySource;
}
4.NacosPropertySourceBuilder.loadNacosData()调用了ConfigService.getConfig(dataId, group, timeout);
ConfigService实现NacosConfigService
@Override
public String getConfig(String dataId, String group, long timeoutMs) throws NacosException {
return getConfigInner(namespace, dataId, group, timeoutMs);
}
private String getConfigInner(String tenant, String dataId, String group, long timeoutMs) throws NacosException {
group = null2defaultGroup(group);
ParamUtils.checkKeyParam(dataId, group);
ConfigResponse cr = new ConfigResponse();
cr.setDataId(dataId);
cr.setTenant(tenant);
cr.setGroup(group);
// 优先使用本地文件目录下配置
String content = LocalConfigInfoProcessor.getFailover(agent.getName(), dataId, group, tenant);
if (content != null) {
LOGGER.warn("[{}] [get-config] get failover ok, dataId={}, group={}, tenant={}, config={}", agent.getName(),
dataId, group, tenant, ContentUtils.truncateContent(content));
cr.setContent(content);
configFilterChainManager.doFilter(null, cr);
content = cr.getContent();
return content;
}
try {
//从server端拉取配置
String[] ct = worker.getServerConfig(dataId, group, tenant, timeoutMs);
cr.setContent(ct[0]);
configFilterChainManager.doFilter(null, cr);
content = cr.getContent();
return content;
} catch (NacosException ioe) {
if (NacosException.NO_RIGHT == ioe.getErrCode()) {
throw ioe;
}
LOGGER.warn("[{}] [get-config] get from server error, dataId={}, group={}, tenant={}, msg={}",
agent.getName(), dataId, group, tenant, ioe.