SpringBoot源码(4)外部化配置


一、外部化配置

1、外部化配置资源类型

先来看看外部化配置的几种资源类型,除了 propertiesYAML 外,还有环境变量、系统属性、启动参数等。所有的资源类型将近二十种,这里只介绍我们比较熟悉的:

  1. properties :这个应该都知道,就是在以 .properties 为后缀的文件中定义key value格式数据。
  2. YAML:文件格式是以 .yml 为后缀,文件中的数据也是key value格式,如下:
user:
  name: rewind
  age: 10

这里的key就是 user.nameuser.age

  1. 环境变量:这是通过 System.getenv() 方式获取的默认配置,也是key value格式,下面列出部分配置,其它的还请自行了解,如下:
名称 Key
Java安装目录 JAVA_HOME
classpath环境变量 CLASSPATH
用户临时文件目录 TEMP
计算机名 COMPUTERNAME
用户名 USERNAME
  1. 系统属性:这是通过 System.getProperties() 方式获取的默认配置,也是key value格式,下面列出部分配置,其它的还请自行了解,如下:
名称 Key
运行时环境版本 java.version Java
Java安装目录 java.home
要使用的 JIT编译器的名称 java.compiler
操作系统的架构 os.arch
操作系统的版本 os.version
  1. 启动参数:一种是在 jar 包运行时行时传递的参数,如:java -jar xxx.jar name=张三 pwa=123 ,还有一种是在 IDEA 的启动编辑配置的 Program arguments 中输入数据:name=张三

可以看到,外部化配置中的数据都是key value 格式。这里还要注意它们的加载顺序,当key相同时,会出现覆盖的情况。

2、外部化配置的核心

首先来看取值方式,在 Spring 时代有 Environment@ValueXML 三种方式,在 Spring Boot 时代则是 @ConfigurationProperties 方式。其中,涉及到了一个核心类,它就是 Environment ,该对象不仅可以获取所有的外部化配置数据,就连另外几种取值方式的数据来源也是从该类中获取。这里,主要对 Environment@ConfigurationProperties 进行详细讨论, Environment@ConfigurationPropertiesSpring Boot 外部化配置的核心所在。

二、Environment

1、加载配置

public class SpringApplication {

    ...

    public ConfigurableApplicationContext run(String... args) {
        ...

        try {
            ...

            ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);

        ...

    }
    ...
}

SpringApplication 运行阶段的 run 方法中通过 prepareEnvironment 方法了创建 ConfigurableEnvironment 接口的实现类对象(该接口继承自 Environment),ConfigurableEnvironment 是一个接口,且继承了 Environment 。进入创建方法:

private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
            ApplicationArguments applicationArguments) {
    ConfigurableEnvironment environment = getOrCreateEnvironment();
    configureEnvironment(environment, applicationArguments.getSourceArgs());
    listeners.environmentPrepared(environment);
    bindToSpringApplication(environment);
    if (!this.isCustomEnvironment) {
        environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
                deduceEnvironmentClass());
    }
    ConfigurationPropertySources.attach(environment);
    return environment;
}

  目录