在我们使用 SpringBoot 开发过程中,会在配置文件(application.properties 或者 application.yml)中写一些公共的配置,那么 SpringBoot 是如何加载配置文件的呢?
1. 发布事件
结合我们前面介绍的SpringBoot中的监听事件机制,我们首先看下SpringApplication.run()方法,在该方法中会针对SpringBoot项目启动的不同的阶段来发布对应的事件。
2. 监听器
监听这个事件的监听器是EnvironmentPostProcessorApplicationListener,所以我们看下这个监听器都干了些什么?
开始处理执行实现 EnvironmentPostProcessor类的postProcessEnvironment方法。
实现EnvironmentPostProcessor的类有 6 个
Spring Boot使用ConfigDataEnvironmentPostProcessor来加载配置文件。这个类实现了EnvironmentPostProcessor接口,它的postProcessEnvironment方法会被调用,以加载配置数据。
在postProcessEnvironment这个方法中,创建ConfigDataEnvironment实例,然后执行其processAndApply
这里主要创建ConfigDataLocationResolvers,ConfigDataLoaders以及ConfigDataEnvironmentContributors。
加载配置文件位置解析器
配置数据加载器,将配置文件的内容解析成应用程序可用的配置信息。
接下来我们再看回去看ConfigDataEnvironment类的构造方法中this.contributors = createContributors(binder);这段代码
这里决定了配置文件加载的顺序
由上面的代码可知:
配置文件的定义顺序为:
optional:classpath:/
optional:classpath:/config/
optional:file:./
optional:file:./config/
optional:file:./config/*/
配置文件加载顺序为:
file:./
file:./config/
file:./config/*/
classpath:/
classpath:/config/
接下来,开始执行processAndApply()方法了。
这里就开始加载和解析配置文件了
resolve 解析
resolve会调用ConfigDataEnvironment中创建的解析器,比如:StandardConfigDataLocationResolver,然后去解析ConfigDataEnvironmentContributor中保存的配置文件的路径。StandardConfigDataLocationResolver会先把路径拿出来按照;进行拆分
(方法在ConfigDataLocation中),然后组装每个路径下的文件位置信息,对于文件名默认都为application,对于文件类型,需要使用到PropertySourceLoader他有两个子类:YamlPropertySourceLoader和PropertiesPropertySourceLoader,通过getFileExtensions方法获取文件类型。其中PropertiesPropertySourceLoader对应properties和xml,而YamlPropertySourceLoader对应yml以及yaml。
这样就可以用ConfigDataLocation路径+applicaiton+getFileExtensions得到一组文件路径。
然后解析器会检查这些文件是否存在,如果不存在的则会过滤掉。
最后将找到的文件放入StandardConfigDataResource集合中返回,由load方法去加载数据。
load 加载:
load方法将resolve方法解析出来的文件路径,有对应的加载器去文件中将数据取出来。
这里需要注意的是,读取文件是从最后一个开始读取,即跟文件加载顺序相反,所以配置加载顺序为:
file:./config/*/
file:./config/
file:./
classpath:/config/
classpath:/
将读取的数据封装到ConfigData当中返回。最后将数据组装到ConfigDataEnvironmentContributors中,最后把数据放入当前应用环境中