文章目录

  • 一、介绍
  • 二、配置系统属性和环境变量
  • 三、配置自定义属性命令行参数
  • 四、作为应用配置信息


一、介绍

在上一篇文章:springboot创建并配置环境(一) - 创建环境中我们探讨了springboot是如何根据当前应用程序类型去创建对应的环境实例的。接下来探讨如何去配置完善该运行环境。

下面我们以标准环境StandardEnvironment为例进行分析。

二、配置系统属性和环境变量

首先我们应该判断在创建一个运行环境实例对象时,在构造器内部是否就已经开始对某些配置属性进行处理了。

在创建运行环境实例时,是通过标准环境StandardEnvironment的无参构造方法完成的,进入该构造方法后发现它是一个空方法

springboot 根据环境判断 springboot设置环境变量_java

由于该类继承于AbstractEnvironment,那么在执行StandardEnvironment的构造方法时会默认先调用父类的无参构造方法,接下来再看父类的无参构造。

springboot 根据环境判断 springboot设置环境变量_java_02

在该无参构造中,先实例化一个MutablePropertySources对象,然后再调用了下面的有参构造方法,并对propertySourcespropertyResolver这两个属性进行初始化。

  • MutablePropertySources
    该类内部维护了一个PropertySource集合,该集合中保存着大量以key,value形式的属性配置,且value值可以是任何数据类型。mutable意为可变的,表示允许调用方去修改其内部的属性配置。如下图所示

看到PropertiySource大家是否还有印象,我们在springboot从命令行读取应用程序参数这篇文章中有介绍过,它其实就是一个以key,value形式的属性配置对象,且value值可以是任何数据类型(用泛型T表示)。

  • propertySources
    该属性指向MutablePropertySources对象。
  • propertyResolver
    属性解析器,提供一些从propertySources中获取所需要的属性的方法。

该运行环境实例的两个重要属性初始化完成后,该实例就具备了利用属性解析器propertyResolver解析配置属性并将解析后的结果保存到propertySources中的功能了。

接下来我们再看customizePropertySources()方法做了什么?从命名上来看,它可以自定义地添加一些属性,查看该方法是一个空方法

springboot 根据环境判断 springboot设置环境变量_springboot 根据环境判断_03

那么我们再回到它的子类StandardEnvironment查看该方法实现。

springboot 根据环境判断 springboot设置环境变量_spring boot_04

在该方法中,我们可以看到,通过调用MutablePropertySourcesaddLast()方法,向其内部的PropertySource集合尾部添加两种属性:PropertiesPropertySourceSystemEnvironmentPropertySource

这两个类都是PropertiySource抽象类的实现类,用于保存不同类型的属性,但他们本质上都是PropertiySource实例。其中

  • PropertiesPropertySource
    该类用于保存系统属性,其中key为systemPropertiesvalue为Map集合,该集合中保存所有系统属性
  • SystemEnvironmentPropertySource
    该类用于保存系统环境变量,其中key为systemEnvironmentvalue为Map集合,该集合中保存所有系统环境变量

另外,PropertiySource还有很多种不同的实现类,用于保存不同类型的属性,如下所示

springboot 根据环境判断 springboot设置环境变量_java_05

下面我们用图示将当前已经保存的属性、以及目前运行环境保存属性的结构表示出来

springboot 根据环境判断 springboot设置环境变量_后端_06

好了,说了这么多我会不会是在瞎说,我们测一下就好了,把断点打在创建标准环境StandardEnvironment实例的下一行,查看此时运行环境中的属性

springboot 根据环境判断 springboot设置环境变量_后端_07

  • 系统属性
    从调试中我们看到,springboot找到了64个系统属性
  • 系统环境变量
    从调试中我们看到,springboot找到了65个系统环境变量

三、配置自定义属性命令行参数

自定义属性主要是来自命令行参数。在前面的文章springboot读取命令行参数中我们已经详细介绍过springboot是如何读取命令行参数并将其保存在ApplicationArguments对象中的,但这些来自命令行的参数目前并不能作为启动环境信息、,需要将其也保存到启动环境中。

我们继续读prepareEnvironment()方法源码,来到configureEnvironment()这一行,

springboot 根据环境判断 springboot设置环境变量_spring_08

进入configureEnvironment()方法,该方法的逻辑主要分三部分,其中第一部分设置类型转换器

springboot 根据环境判断 springboot设置环境变量_后端_09

该方法的处理逻辑主要分三部分

  • 设置类型转换器
    该部分逻辑只是向环境中设置一些springboot内置的类型转换器Convertor,本篇文章不具体展开来讲。
  • 配置自定义的普通参数
  • 首先将默认属性配置添加到MutablePropertySources的尾部
    默认属性配置的设置方法是通过SpringApplication对象的setDefaultProperties()方法设置的,如下所示
  • 配置命令行参数
    在前面的文章springboot读取命令行参数我们已经详细介绍过springboot如何将命令行参数转为SimpleCommandLinePropertySource,本文就不再赘述。
    在这一步会先判断我们已经保存的属性配置中是否已经存在key=commandLineArgs了,从我们逐行阅读源码的过程中我们可以断定是不存在这样的属性的,因此会执行else代码块,即只需要将SimpleCommandLinePropertySource添加到已经保存的属性配置的首部即可。
    此时我们再次用图示将当前已经保存的属性、以及目前运行环境保存属性的结构表示出来

当然了,如果你想拒绝任何来自命令行的属性参数,可以通过以下方法将addCommandLineProperties属性设置为false,这样springboo就不会把命令行参数保存到启动环境中了

springboot 根据环境判断 springboot设置环境变量_springboot 根据环境判断_10

  • 配置来自命令行的profile
    该方法为空方法,保留该方法方面日后扩展。

四、作为应用配置信息

在处理完自定义的属性后,下一步springboot需要对当前启动环境中的属性配置适配ConfigurationPropertySources的支持,如下图所示

springboot 根据环境判断 springboot设置环境变量_springboot 根据环境判断_11

进入attach()方法,如下所示

springboot 根据环境判断 springboot设置环境变量_springboot 根据环境判断_12

该方法执行后的结果就是将当前启动环境中已保存的属性配置source封装到一个ConfigurationPropertySourcesPropertySource对象中,并且对应的key=configurationProperties,此时启动环境中保存的属性配置如下所示

springboot 根据环境判断 springboot设置环境变量_springboot 根据环境判断_13

至于为什么这么做,我们可以看一下方法注释:

Attach a ConfigurationPropertySource support to the specified Environment. Adapts each PropertySource managed by the environment to a ConfigurationPropertySource and allows classic PropertySourcesPropertyResolver calls to resolve using configuration property names.
The attached resolver will dynamically track any additions or removals from the underlying Environment property sources.

从注释中得知,该方法的目的就是真正的把当前保存在启动环境中的这些propertySources作为配置属性,就是说这些属性在此之前springboot并没有把他们作为配置来看,如今它们成为了配置属性