SpringBoot配置文件读取过程分析

打印 上一主题 下一主题

主题 850|帖子 850|积分 2560

整体流程分析

SpringBoot的配置文件有两种 ,一种是 properties文件,一种是yml文件。在SpringBoot启动过程中会对这些文件进行解析加载。在SpringBoot启动的过程中,配置文件查找和解析的逻辑在listeners.environmentPrepared(environment)方法中。
  1. void environmentPrepared(ConfigurableEnvironment environment) {
  2.     for (SpringApplicationRunListener listener : this.listeners) {
  3.         listener.environmentPrepared(environment);
  4.     }
  5. }
复制代码
依次遍历监听器管理器的environmentPrepared方法,默认只有一个 EventPublishingRunListener 监听器管理器,代码如下,
  1. @Override
  2. public void environmentPrepared(ConfigurableEnvironment environment) {
  3.     this.initialMulticaster
  4.         .multicastEvent(new ApplicationEnvironmentPreparedEvent(this.application, this.args, environment));
  5. }
复制代码
监听管理器的多播器有中有11个,其中针对配置文件的监听器类为 ConfigFileApplicationListener,会执行该类的 onApplicationEvent方法。代码如下,
  1. @Override
  2. public void onApplicationEvent(ApplicationEvent event) {
  3.     if (event instanceof ApplicationEnvironmentPreparedEvent) {
  4.         // 执行 ApplicationEnvironmentPreparedEvent 事件
  5.         onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent) event);
  6.     }
  7.     if (event instanceof ApplicationPreparedEvent) {
  8.         onApplicationPreparedEvent(event);
  9.     }
  10. }
复制代码
onApplicationEnvironmentPreparedEvent的逻辑为:先从/META-INF/spring.factories文件中获取实现了EnvironmentPostProcessor接口的环境变量后置处理器集合,再把当前的 ConfigFileApplicationListener 监听器添加到 环境变量后置处理器集合中(ConfigFileApplicationListener实现了EnvironmentPostProcessor接口),然后循环遍历 postProcessEnvironment 方法,并传入 事件的SpringApplication 对象和 环境变量。
  1. private void onApplicationEnvironmentPreparedEvent(ApplicationEnvironmentPreparedEvent event) {
  2.     List<EnvironmentPostProcessor> postProcessors = loadPostProcessors();
  3.     postProcessors.add(this);
  4.     AnnotationAwareOrderComparator.sort(postProcessors);
  5.     for (EnvironmentPostProcessor postProcessor : postProcessors) {
  6.         postProcessor.postProcessEnvironment(event.getEnvironment(), event.getSpringApplication());
  7.     }
  8. }
复制代码
在ConfigFileApplicationListener 的postProcessEnvironment方法中(其他几个环境变量后置处理器与读取配置文件无关),核心是创建了一个Load对象,并且调用了load()方法。
  1. protected void addPropertySources(ConfigurableEnvironment environment, ResourceLoader resourceLoader) {
  2.     RandomValuePropertySource.addToEnvironment(environment);
  3.     new Loader(environment, resourceLoader).load();
  4. }
复制代码

  • Loader是ConfigFileApplicationListener 的一个内部类,在Loader的构造方法中,会生成具体属性文件的资源加载类并赋值给this.propertySourceLoaders。代码如下,
  1. Loader(ConfigurableEnvironment environment, ResourceLoader resourceLoader) {
  2.     this.environment = environment;
  3.     this.placeholdersResolver = new PropertySourcesPlaceholdersResolver(this.environment);
  4.     this.resourceLoader = (resourceLoader != null) ? resourceLoader : new DefaultResourceLoader();
  5.     //从 /META-INF/spring.factories 中加载 PropertySourceLoader 的实现类
  6.     this.propertySourceLoaders = SpringFactoriesLoader.loadFactories(PropertySourceLoader.class,
  7.                                                                      getClass().getClassLoader());
  8. }
复制代码
从 /META-INF/spring.factories 中加载 PropertySourceLoader 的实现类,在具体解析资源文件的时候用到。具体的实现类如下,
  1. org.springframework.boot.env.PropertySourceLoader=\
  2. org.springframework.boot.env.PropertiesPropertySourceLoader,\
  3. org.springframework.boot.env.YamlPropertySourceLoader
复制代码

  • Loader类的load方法是加载配置文件的入口方法,代码如下,
  1. void load() {
  2.     FilteredPropertySource.apply(...)
  3. }
复制代码
FilteredPropertySource.apply()方法先判断是否存在以 defaultProperties 为名的 PropertySource 属性对象,如果不存在则执行operation.accept,如果存在则先替换,再执行operation.accept方法。代码如下:
[code]static void apply(ConfigurableEnvironment environment, String propertySourceName, Set filteredProperties,                  Consumer
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

来自云龙湖轮廓分明的月亮

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表