运行源码分析:初始化ApplicationArguments( 二 )


.转换环境:判断是否是定制的环境 , 如果不是定制的 , 则将环境转换为Standard-Environment 。 此时判断条件 isCustomEnvironment 默认为 false,在后面的操作中会将其设置为 true,如果为 true 则不再会进行此转换操作 。
:ConfigurationPropertySources 附加到指定环境:将 ConfigurationPropertySources 附加到指定环境中的第一位 , 并动态跟踪环境的添加或删除操作 。
下面针对以上步骤挑选部分代码进行相应的讲解 。
运行源码分析:初始化ApplicationArguments文章插图
获取或创建环境
SpringApplication 类中通过 getOrCreateEnvironment 方法来获取或创建环境 。 在该方法中首先判断环境是否为 null , 如果不为 null 则直接返回;如果为 null,则根据前面推断出来的WebApplicationType 类型来创建指定的环境 , 代码如下 。
【运行源码分析:初始化ApplicationArguments】private Conf igurableEnvironment getOrCreateEnvironment() {if (this. environment != null) {return this . environment;//根据不同的应用类型 ,创建不同的环境实现switch (this . webApplicationType) {case SERVLET:return new StandardServletEnvironment();case REACTIVE:return new StandardReactiveWebEnvironment();default:return new StandardEnvironment();}. 上面方法中如果 environment 存在 ,则直接返回;如果 environment 不存在 , 则根据前面步骤中推断获得的 WebApplicationType 来进行区分创建环境 。 如果是 SERVLET 项目则创建标准的 Servlet 环境 StandardServletEnvironment;
如果是 REACTIVE 项目则创建 StandardReactiveWebEnvironment;其他情况则创建标准的非 Web 的 StandardEnvironment 。
配置环境
在获得环境变量对象之后 , 开始对环境变量和参数进行相应的设置 , 主要包括转换服务的设置、PropertySources 的设置和 activeProfiles 的设置 。
SpringApplication 类中相关 configureEnvironment 方法代码如下 。
protected void configureEnvironment (ConfigurableEnvironment environment,String[] args) {//如果为 true 则获取并设置转换服务f (this. addConversionService) {ConversionService conversionService = ApplicationConversionService. getSharedInstance();environment . setConversionService( (ConfigurableConvers ionService) conversion-Service);//配置 PropertySourcesconfigurePropertySources( environment, args);//配置 ProfilesconfigureProfiles(environment, args);}在以上代码中 , 首先判断 addConversionService 变量是否为 true, 也就是判断是否需要添加转换服务 , 如果需要 , 则获取转换服务实例 , 并对环境设置转换服务 。 随后进行PropertySources 和 Profiles 的配置 。
其中 configurePropertySources 方法对 PropertySources 进行配置 , 代码如下 。
protected void configurePropertySources (ConfigurableEnvironment environmenString[] args) {//获得环境中的属性资源信息MutablePropertySources sources = environment . getPropertySources();// 如果默认属性配置存在则将其放置于属性资源的最后位置if (this . defaultProperties != null // 如果命令行属性存在if (this . addCommandL ineProperties //如果默认属性资源中不包含该命令 ,则将命令行属性放置在第一 位 , 如果包含 , 则通过Composite-PropertySource 进行处理if (sources . contains(name)) {PropertySource source = sources.get(name);CompositePropertySource composite = new CompositePropertySource(name);composite . addPropertySource (new SimpleCommandLinePropertySource("springApplicationCommandLineArgs", args));composite . addPropertySource(source);sources . replace(name, composite);t else//放置在第一位sources . addFirst(new SimpleCommandL inePropertySource(args));}}}这段代码需要重点看一下参数的优先级处理和默认参数 与命令参数之间的关系 。 首先 , 如果存在默认属性配置 , 则将默认属性配置放置在最后 , 也就是说优先级最低 。 然后 , 如果命令参数存在则会 出现两种情况:如果命令的参数 已经存在于属性配置中 , 则使用CompositePropertySource 类进行相同 name 的参数处理;如果命令的参数并不存在于属性配置中 , 则直接将其设置为优先级最高 。
ConfigurePropertySources 方法的官方注释也很好地解释了它的功能:增加、移除或重新排序应用环境中的任何 PropertySource 。
完成了 PropertySources 配置 , 随后通过 configureProfiles 方法来完成 Profiles 的配置 , 代码如下 。
protected void configureProfiles (ConfigurableEnvironment environment, String[] args)// 保 证 环 境 的 activeProfiles 属 性 被 初 始 化,如 果 未 初 始 化 该 方 法 会 对 其 初 始 化environment . getActiveProfiles();//如果存在的额外的 Profiles,则将其放置在第- -位 ,随后再获得其他的 ProfilesSetprofiles = new LinkedHashSet