SpringBoot 源码 | prepareEnvironment 方法解析
SpringBoot
在 SpringBoot 启动流程中,主要的两个阶段是初始化 SpringApplication 对象以及 SpringApplication.run 方法执行的内容,今天主要细讲的是 SpringApplication.run 中的准备环境的 prepareEnvironment 方法源码 ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments)。prepareEnvironment 的源码如下
prepareEnvironment 源码
prepareEnvironment 主要包含方法 getOrCreateEnvironment、configureEnvironment、ConfigurationPropertySources.attach、DefaultPropertiesPropertySource.moveToEnd、bindToSpringApplication,

这里我们先来为每行代码加上对应的注释
复制代码
首先来看方法 getOrCreateEnvironment
getOrCreateEnvironment
官方注释 Create and configure the environment 创建和配置环境,由于我们的是 SERVLET 类型,所以这里会返回 ApplicationServletEnvironment 对象

configureEnvironment
继续往下执行看到 configureEnvironment 方法,configureEnvironment 方法主要是配置 property sources or profiles,源码可以看到

configurePropertySources
继续跟进 configurePropertySources 方法可以看到官方注释 Add, remove or re-order any {@link PropertySource}s in this application's environment 意为在此应用程序环境中添加、删除或重新排序任何{@link PropertySource},源码如下

其中方法 environment.getPropertySources()主要是为了获取 ApplicationServletEnvironment 中的 PropertySources,获取之后会判断 Map defaultProperties;是否不为 null,不为 null 则执行 addOrMerge 判断是需要新增或者合并 DefaultPropertiesPropertySource

回到 configurePropertySources 方法向下执行,

这里的 args 是 the application arguments (usually passed from a Java main method)从 run 方法带下来的参数,这里判断 args 的长度是否大于 0,满足条件后判断当前 sources 中是否包含命令行参数,包含的话就需要用 args 中参数替换 sources 中对应 name 的参数,如果不包含则直接把 args 放在首位,
configureProfiles
我们再来看 configureProfiles 方法,可以看到

官方注释 Configure which profiles are active (or active by default) for this application environment. Additional profiles may be activated during configuration file processing via the {@code spring.profiles.active} property.的意思也就是说在配置文件处理过程中,可以通过{@code-spring.profiles.active}属性激活其他配置文件。
具体的实现去查看 ConfigFileApplicationListener 类 By default properties will be loaded from
'application.properties' and/or 'application.yml' files in the following locations 属性内容会从 application.properties 或者 application.yml 加载,继续向下执行
ConfigurationPropertySources.attach
ConfigurationPropertySources.attach 方法

主要是为了将 ConfigurationPropertySource 附加到指定 Environment,遍历 Environment 管理的每个 PropertySource 到 ConfigurationPropertySource 同时允许 PropertySourcesPropertyResolver 调用使用 ConfigurationPropertyName 配置的属性名,同时放在首位,之后 listeners.environmentPrepared 完成环境准备
DefaultPropertiesPropertySource.moveToEnd
之后调用 DefaultPropertiesPropertySource.moveToEnd 将 Move the 'defaultProperties' property source so that it's the last source 移动到 source 末尾

bindToSpringApplication
环境参数配置完成之后执行 bindToSpringApplication 将环境配置参数绑定到 SpringApplication

convertEnvironment
如果 isCustomEnvironment 为 false 则将 ConfigurableEnvironment 转换为 application environment 并且不直接解析配置文件属性的应用程序环境

最后再执行一次 ConfigurationPropertySources.attach,完成之后返回环境配置对象 ConfigurableEnvironment,至此 prepareEnvironment 方法执行完成。
总结
执行完成准备环境的 prepareEnvironment 方法之后,会继续执行容器上下文启动前的其他准备工作,后续我会继续更新,欢迎共同讨论,一同进步。
评论