spring源码-配置文件加载原理

spring应用在启动时会调用SpringApplication.java类中的prepareEnvironment()方法来加载配置文件。

  1. 创建环境:根据应用类型判断是SERVLET->StandardServletEnvironment还是REACTIVE->StandardReactiveWebEnvironment。在SpringApplication类实例化的时候通过WebApplicationType.deduceFromClasspath()判断当前的应用类型。如果org.springframework.web.reactive.DispatcherHandler类存在则是WebApplicationType.REACTIVE;如果javax.servlet.Servlet和org.springframework.web.context.ConfigurableWebApplicationContext都不存在则WebApplicationType.NONE,即啥都不是,相反当有一个存在就是WebApplicationType.SERVLET。确定了应用类型后就创建StandardServletEnvironment的实例对象。
  2. 为环境进行配置:设置类型转换服务(ApplicationConversionService.sharedInstance)。
    1. 将命令行参数封装成SimpleCommandLinePropertySource对象。
      1. 遍历命令行参数,即主类中main接受的String[]
      2. 将每个参数添加到CommandLineArgs的属性nonOptionArgs(ArrayList)中
      3. 创建SimpleCommandLinePropertySource(extends PropertySource)对象,name为commandLineArgs,source为CommandLineArgs
    2. 添加profiles
  3. 创建名为configurationProperties的配置属性源ConfigurationPropertySourcesPropertySource
  4. 发布ApplicationEnvironmentPreparedEvent事件,ConfigFileApplicationListener监听器会处理这个事件。
  5. ConfigFileApplicationListener监听器会加载环境后置处理器EnvironmentPostProcessor:到spring.factories中找到EnvironmentPostProcessor接口的实现类进行实例化,并将ConfigFileApplicationListener本身加入,之后依次调用每个处理器进行处理

SystemEnvironmentPropertySourceEnvironmentPostProcessor

获取"systemEnvironment"属性源,即系统环境变量,封装成SystemEnvironmentPropertySource对象保存下来

SpringApplicationJsonEnvironmentPostProcessor

处理json格式的属性源

ConfigFileApplicationListener

重头戏来了,就是这个类处理配置文件的加载的。

  1. 创建个Loader加载器,加载器内部持有占位符解析器,解析${};通过spring.factories加载属性源加载器,分别是PropertiesPropertySourceLoader(properties/xml)和YamlPropertySourceLoader(yaml/yml),调用load()方法进行加载。
  2. 到"classpath:/,classpath:/config/,file:./,file:./config/*/,file:./config/"这些路径下加载配置文件。
private void load(Profile profile, DocumentFilterFactory filterFactory, DocumentConsumer consumer) {
    //getSearchLocations()方法返回:"classpath:/,classpath:/config/,file:./,file:./config/*/,file:./config/"
    getSearchLocations().forEach((location) -> {
        boolean isDirectory = location.endsWith("/");
        Set<String> names = isDirectory ? getSearchNames() : NO_SEARCH_NAMES;
        names.forEach((name) -> load(location, name, profile, filterFactory, consumer));
    });
} 
  1. 默认加载的分别是application开头、default开头的文件名,使用刚刚从spring.factories加载的属性源加载器来解读配置文件。到每个路径下获取Resource资源getResources(location)。使用applicationConfig: [classpath:/application.properties]表示获取到的属性源。读取对应的配置文件,获取每个配置。
    1. 创建CharacterReader读取每个字符
    2. 读取配置文件中的key,读取每个字符到’=‘或’:'为止,将读到的字符buffer.append下来,最终得到的字符串为key
    3. 在没有读取到换行符时继续读取每个字符,将读到的字符buffer.append下来,最终得到的字符串为value
    4. 将读取的key和value添加到LinkedHashMap
  2. 加载了文件以后将缓存下来,将读取到的属性源添加到环境中
    这样就完成了配置源的加载,最终所有的属性都保存在StandardServletEnvironment的属性propertySources中,可以通过this.environment.getPropertySources()获取到。当获取某个具体的配置时,对所有的配置源进行遍历,通过key获取具体的值。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值