Nacos配置文件的加载

SpringBoot启动时,初始化完成运行环境信息准备之后,会调用SpringApplication.prepareContext方法开始准备上下文,在prepareContext方法中会通过applyInitializers方法调用所有实现了ApplicationContextInitializer类的实例。

protected void applyInitializers(ConfigurableApplicationContext context) {
    //获取所有实现了ApplicationContextInitializer的类,主要看PropertySourceBootstrapConfiguration
    Iterator var2 = this.getInitializers().iterator();
    while(var2.hasNext()) {
        ApplicationContextInitializer initializer = (ApplicationContextInitializer)var2.next();
        Class requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(), ApplicationContextInitializer.class);
        Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
        initializer.initialize(context);
    }
}

PropertySourceBootstrapConfiguration.initialize方法

public void initialize(ConfigurableApplicationContext applicationContext) { 
	List<PropertySource<?>> composite = new ArrayList<>(); 
	//对propertySourceLocators数组进行排序
	AnnotationAwareOrderComparator.sort(this.propertySourceLocators); 
	boolean empty = true; 
	//获取运行的环境上下文 
	ConfigurableEnvironment environment = applicationContext.getEnvironment(); 
	for (PropertySourceLocator locator : this.propertySourceLocators) { 
		//通过PropertySourceLocator接口实例的locate方法,加载远程的配置文件 
		Collection<PropertySource<?>> source = locator.locateCollection(environment); 
		if (source == null || source.size() == 0) { 
			continue; 
		}
		List<PropertySource<?>> sourceList = new ArrayList<>(); 
		for (PropertySource<?> p : source) {
			sourceList.add(new BootstrapPropertySource<>(p)); 
		}
		logger.info("Located property source: " + sourceList); 
		composite.addAll(sourceList);//将source添加到数组 
		empty = false;
	}
	if (!empty) { 
		MutablePropertySources propertySources = environment.getPropertySources(); 
		String logConfig = environment.resolvePlaceholders("${logging.config:}"); 
		LogFile logFile = LogFile.get(environment); 
		for (PropertySource<?> p : environment.getPropertySources()) { 
			if (p.getName().startsWith(BOOTSTRAP_PROPERTY_SOURCE_NAME)) { 
				propertySources.remove(p.getName()); 
			} 
		}
        //将远程的配置文件加载到propertySources的头部
		insertPropertySources(propertySources, composite); 
		reinitializeLoggingSystem(environment, logConfig, logFile); 
		setLogLevels(applicationContext, environment); 
		handleIncludedProfiles(environment); 
	} 
}
PropertySourceLocator.locateCollection方法
static default Collection<PropertySource<?>> locateCollection(PropertySourceLocator locator, Environment environment) {
    //调用PropertySourceLocator实现类的locate方法,主要看NacosPropertySourceLocator.locate
    PropertySource propertySource = locator.locate(environment);
    if(propertySource == null) {
        return Collections.emptyList();
    } else if(CompositePropertySource.class.isInstance(propertySource)) {
        Collection sources = ((CompositePropertySource)propertySource).getPropertySources();
        ArrayList filteredSources = new ArrayList();
        Iterator var5 = sources.iterator();
        while(var5.hasNext()) {
            PropertySource p = (PropertySource)var5.next();
            if(p != null) {
                filteredSources.add(p);
            }
        }
        return filteredSources;
    } else {
        return Arrays.asList(new PropertySource[]{propertySource});
    }
}

NacosPropertySourceLocator.locate

public PropertySource<?> locate(Environment env) {
    this.nacosConfigProperties.setEnvironment(env);
    ConfigService configService = this.nacosConfigManager.getConfigService();
    if(null == configService) {
        log.warn("no instance of config service found, can\'t load config from nacos");
        return null;
    } else {
        long timeout = (long)this.nacosConfigProperties.getTimeout();
        this.nacosPropertySourceBuilder = new NacosPropertySourceBuilder(configService, timeout);
        String name = this.nacosConfigProperties.getName();
        String dataIdPrefix = this.nacosConfigProperties.getPrefix();
        if(StringUtils.isEmpty(dataIdPrefix)) {
            dataIdPrefix = name;
        }
        if(StringUtils.isEmpty(dataIdPrefix)) {
            dataIdPrefix = env.getProperty("spring.application.name");
        }
        CompositePropertySource composite = new CompositePropertySource("NACOS");
        //加载共享配置,配置文件优先级最低
        this.loadSharedConfiguration(composite);
        //加载拓展配置
        this.loadExtConfiguration(composite);
        //加载自身配置,配置文件优先级最高
        this.loadApplicationConfiguration(composite, dataIdPrefix, this.nacosConfigProperties, env);
        return composite;
    }
}

NacosPropertySourceLocator.loadSharedConfiguration加载共享配置,通过在bootstrap.properties中的spring.cloud.nacos.config.shared-configs进行配置,设置dataId,group等属性如果想要此配置支持自动刷新,需要设置refresh属性为true,默认为false,不支持自动刷新。

private void loadSharedConfiguration(CompositePropertySource compositePropertySource) {
    //获取bootstrap.properties中spring.cloud.nacos.config.sharedConfigs的配置
    List sharedConfigs = this.nacosConfigProperties.getSharedConfigs();
    if(!CollectionUtils.isEmpty(sharedConfigs)) {
        //检查配置文件类型是否支持
        this.checkConfiguration(sharedConfigs, "shared-configs");
        //加载配置文件
        this.loadNacosConfiguration(compositePropertySource, sharedConfigs);
    }
}

NacosPropertySourceLocator.checkConfiguration检查配置文件的类型是否支持,默认支持properties类型的配置文件类型,可以通过spring.cloud.nacos.config.file-extension设置

private void checkConfiguration(List<Config> configs, String tips) {
    String[] dataIds = new String[configs.size()];
    for(int i = 0; i < configs.size(); ++i) {
        String dataId = ((Config)configs.get(i)).getDataId();
        if(dataId == null || dataId.trim().length() == 0) {
            throw new IllegalStateException(String.format("the [ spring.cloud.nacos.config.%s[%s] ] must give a dataId", new Object[]{tips, Integer.valueOf(i)}));
        }
        dataIds[i] = dataId;
    }
    //检查dataId的文件类型Nacos是否支持,默认支持properties,可以通过spring.cloud.nacos.config.file-extension
    //配置增加xml,yml,yaml,json等类型文件
    NacosDataParserHandler.getInstance().checkDataId(dataIds);
}

NacosPropertySourceLocator.loadNacosConfiguration

private void loadNacosConfiguration(CompositePropertySource composite, List<Config> configs) {
    Iterator var3 = configs.iterator();
    while(var3.hasNext()) {
        Config config = (Config)var3.next();
        String dataId = config.getDataId();
        //截取配置文件类型
        String fileExtension = dataId.substring(dataId.lastIndexOf(".") + 1);
        //加载配置文件
        this.loadNacosDataIfPresent(composite, dataId, config.getGroup(), fileExtension, config.isRefresh());
    }
}

NacosPropertySourceLocator.loadNacosDataIfPresent

private void loadNacosDataIfPresent(CompositePropertySource composite, String dataId, String group, String fileExtension, boolean isRefreshable) {
    if(null != dataId && dataId.trim().length() >= 1) {
        if(null != group && group.trim().length() >= 1) {
            //加载配置文件
            NacosPropertySource propertySource = this.loadNacosPropertySource(dataId, group, fileExtension, isRefreshable);
            //将新加载的配置文件放到composite的头部
            this.addFirstPropertySource(composite, propertySource, false);
        }
    }
}

NacosPropertySourceLocator.loadNacosPropertySource,如果isRefreshable为false,即不支持自动刷新配置文件,从缓存中加载配置文件,isRefreshable为true,从远程加载配置文件

private NacosPropertySource loadNacosPropertySource(String dataId, String group, String fileExtension, boolean isRefreshable) {
    return NacosContextRefresher.getRefreshCount() != 0L && !isRefreshable?
       NacosPropertySourceRepository.getNacosPropertySource(dataId, group):
       this.nacosPropertySourceBuilder.build(dataId, group, fileExtension, isRefreshable);
}

NacosPropertySourceBuilder.build从远端加载配置文件

NacosPropertySource build(String dataId, String group, String fileExtension, boolean isRefreshable) {
    //加载远端的配置文件
    Map p = this.loadNacosData(dataId, group, fileExtension);
    //将Map格式的配置转换为NacosPropertySource 
    NacosPropertySource nacosPropertySource = new NacosPropertySource(group, dataId, p, new Date(), isRefreshable);
    //将配置保存到Map缓存中
    NacosPropertySourceRepository.collectNacosPropertySource(nacosPropertySource);
    return nacosPropertySource;
}

 NacosPropertySourceBuilder.loadNacosData调用通过ConfigService实例调用Nacos远端获取配置文件,ConfigService实例的获取是从NacosConfigManager获取的。NacosConfigManager的实例化通过

NacosConfigAutoConfiguration.nacosConfigManager来完成。

private Map<String, Object> loadNacosData(String dataId, String group, String fileExtension) {
    String data = null;
    try {
        data = this.configService.getConfig(dataId, group, this.timeout);
        if(StringUtils.isEmpty(data)) {
            log.warn("Ignore the empty nacos configuration and get it based on dataId[{}] & group[{}]", dataId, group);
            return EMPTY_MAP;
        }
        if(log.isDebugEnabled()) {
            log.debug(String.format("Loading nacos data, dataId: \'%s\', group: \'%s\', data: %s", new Object[]{dataId, group, data}));
        }
        Map e = NacosDataParserHandler.getInstance().parseNacosData(data, fileExtension);
        return e == null?EMPTY_MAP:e;
    } catch (NacosException var6) {
        log.error("get data from Nacos error,dataId:{}, ", dataId, var6);
    } catch (Exception var7) {
        log.error("parse data from Nacos error,dataId:{},data:{},", new Object[]{dataId, data, var7});
    }
    return EMPTY_MAP;
}
@Bean
public NacosConfigManager nacosConfigManager(NacosConfigProperties nacosConfigProperties) {
    return new NacosConfigManager(nacosConfigProperties);
}
NacosPropertySourceLocator.loadExtConfiguration加载拓展配置,通过在bootstrap.properties中的spring.cloud.nacos.config.extension-configs进行配置,设置dataId,group等属性如果想要此配置支持自动刷新,需要设置refresh属性为true,默认为false,不支持自动刷新。
private void loadExtConfiguration(CompositePropertySource compositePropertySource) {
    List extConfigs = this.nacosConfigProperties.getExtensionConfigs();
    if(!CollectionUtils.isEmpty(extConfigs)) {
        this.checkConfiguration(extConfigs, "extension-configs");
        this.loadNacosConfiguration(compositePropertySource, extConfigs);
    }

}

NacosPropertySourceBuilder.loadApplicationConfiguration加载自身的配置,根据spring.cloud.nacos.config.prefix(默认等于spring.application.name)配置获得配置的文件名称

private void loadApplicationConfiguration(CompositePropertySource compositePropertySource, String dataIdPrefix, NacosConfigProperties properties, Environment environment) {
    String fileExtension = properties.getFileExtension();
    String nacosGroup = properties.getGroup();
    this.loadNacosDataIfPresent(compositePropertySource, dataIdPrefix, nacosGroup, fileExtension, true);
    this.loadNacosDataIfPresent(compositePropertySource, dataIdPrefix + "." + fileExtension, nacosGroup, fileExtension, true);
    String[] var7 = environment.getActiveProfiles();
    int var8 = var7.length;
    for(int var9 = 0; var9 < var8; ++var9) {//循环加载激活的配置
        String profile = var7[var9];
        String dataId = dataIdPrefix + "-" + profile + "." + fileExtension;
        this.loadNacosDataIfPresent(compositePropertySource, dataId, nacosGroup, fileExtension, true);
    }
}
 

猜你喜欢

转载自blog.csdn.net/qq_33513289/article/details/114679450