SpringBoot加载配置文件源码解析

        SpringBoot通过事件广播机制通知ConfigFileApplicationListener这个监听器来加载properties和yaml文件。关于SpringBoot事件编程模型可参考:SpringBoot事件编程模型解析

        SpringBoot一站式启动过程中,会经过环境准备阶段:

ConfigurableEnvironment environment = prepareEnvironment(listeners,
					applicationArguments);

        该过程中,会向监听者广播环境准备完毕的事件:

listeners.environmentPrepared(environment);

        其中ConfigFileApplicationListener监听者接收到该事件后, 会委托EnvionmentPostProcesor环境后置处理器来加载配置文件,这里的ConfigFileApplicationListener的另外一个角色正好是环境后置处理器,所以最终文件加载还是在ConfigFileApplicationListener中完成的。

//继承了环境后置处理器和应用程序监听器
public class ConfigFileApplicationListener
		implements EnvironmentPostProcessor, SmartApplicationListener, Ordered {
    ...
}

        ConfigFileApplicationListener中加载配置文件总领代码如下:       

	protected void addPropertySources(ConfigurableEnvironment environment,
			ResourceLoader resourceLoader) {
		RandomValuePropertySource.addToEnvironment(environment);
		new Loader(environment, resourceLoader).load();
	}

         加载规则如下:先看命令行中是否指定spring.config.location,如果有,则加载指定地址配置文件,如果没有,则按classpath:/,classpath:/config/,file:./,file:./config/优先级加载该路径下的配置文件,可配置spring.profiles.active或者spring.profiles.include加载application-xxx.properties文件,当遇到相同属性时,application-xxx.properties会覆盖application.properties中的该属性,也可配置spring.config.additional-location加载其他路径下的配置文件。

        property和yaml具体的资源加载器分别是:PropertiesPropertySourceLoader、YamlPropertySourceLoader,将配置文件读取到内存其实就是JAVA IO的过程,以classpath路径下配置文件加载为例:

public class PropertiesPropertySourceLoader implements PropertySourceLoader {

	private static final String XML_FILE_EXTENSION = ".xml";

	@Override
	public String[] getFileExtensions() {
		return new String[] { "properties", "xml" };
	}

	@Override
	public List<PropertySource<?>> load(String name, Resource resource)
			throws IOException {
		Map<String, ?> properties = loadProperties(resource);
		if (properties.isEmpty()) {
			return Collections.emptyList();
		}
		return Collections
				.singletonList(new OriginTrackedMapPropertySource(name, properties));
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	private Map<String, ?> loadProperties(Resource resource) throws IOException {
		String filename = resource.getFilename();
		if (filename != null && filename.endsWith(XML_FILE_EXTENSION)) {
			return (Map) PropertiesLoaderUtils.loadProperties(resource);
		}
        //加载
		return new OriginTrackedPropertiesLoader(resource).load();
	}

}

        load过程如下:        

	public Map<String, OriginTrackedValue> load(boolean expandLists) throws IOException {
        //通过ClasspathResource中获取字符流
		try (CharacterReader reader = new CharacterReader(this.resource)) {
			Map<String, OriginTrackedValue> result = new LinkedHashMap<>();
			StringBuilder buffer = new StringBuilder();
			while (reader.read()) {
				String key = loadKey(buffer, reader).trim();
				if (expandLists && key.endsWith("[]")) {
					key = key.substring(0, key.length() - 2);
					int index = 0;
					do {
						OriginTrackedValue value = loadValue(buffer, reader, true);
						put(result, key + "[" + (index++) + "]", value);
						if (!reader.isEndOfLine()) {
							reader.read();
						}
					}
					while (!reader.isEndOfLine());
				}
				else {
					OriginTrackedValue value = loadValue(buffer, reader, false);
					put(result, key, value);
				}
			}
			return result;
		}
	}

        从文件到输入流:

	@Override
	public InputStream getInputStream() throws IOException {
		InputStream is;
		if (this.clazz != null) {
			is = this.clazz.getResourceAsStream(this.path);
		}
		else if (this.classLoader != null) {
			is = this.classLoader.getResourceAsStream(this.path);
		}
		else {
			is = ClassLoader.getSystemResourceAsStream(this.path);
		}
		if (is == null) {
			throw new FileNotFoundException(getDescription() + " cannot be opened because it does not exist");
		}
		return is;
	}

     

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值