Spring Boot启动-构造容器环境

容器的运行环境包含了应用配置和环境相关信息,后面所有关于配置和环境的操作都基于此类。构建容器环境实现代码如下:

    /**
     * 构建容器环境
     * @param listeners  监听器
     * @param applicationArguments  命令行参数
     * @return 构建的环境对象
     */
    private ConfigurableEnvironment prepareEnvironment(
            SpringApplicationRunListeners listeners,
            ApplicationArguments applicationArguments) {
        // 第一步:创建Environment实例
        ConfigurableEnvironment environment = getOrCreateEnvironment();
        // 第二步:配置Environment
        configureEnvironment(environment, applicationArguments.getSourceArgs());
        // 第三步:监听回调
        listeners.environmentPrepared(environment);
        // 第四步:绑定到SpringApplication
        bindToSpringApplication(environment);
        //这一步是非SpringMVC项目的处理,暂时忽略
        if (!this.isCustomEnvironment) {
            environment = new EnvironmentConverter(getClassLoader())
                    .convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());
        }
        // 绑定ConfigurationPropertySourcesPropertySource到ConfigurableEnvironment中,name为configurationProperties,实例是SpringConfigurationPropertySources,属性实际是ConfigurableEnvironment中的MutablePropertySources
        ConfigurationPropertySources.attach(environment);
        return environment;
    }

从代码中可以看到,构建容器环境主要包含四个步骤:

  1. 创建Environment实例
  2. 配置Environment
  3. 监听回调
  4. 绑定到SpringApplication

第一步:创建Environment实例

根据Web应用类型不同,Spring Boot提供了三种容器环境,如果是SERVLET应用,则使用StandardServletEnvironment,如果是REACTIVE应用,则使用StandardReactiveWebEnvironment,其他情况都使用StandardEnvironment。
StandardServletEnvironment和StandardReactiveWebEnvironment都继承自StandardEnvironment,不同之处在于,StandardServletEnvironment增加了加载和解析web.xml配置的逻辑。
具体代码如下:

    private ConfigurableEnvironment 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是当前应用运行环境的公开接口,主要包括应用程序运行环境的两个关键方面:配置文件(profiles)和属性。Environment继承自接口PropertyResolver,而PropertyResolver提供了属性访问的相关方法。
配置Environment包含两部分:

  1. 配置Properties
    // Environment继承关系
    在构建StandardEnvironment对象时,会调用System.getProperty()和System.getEnv()方法,这两个方法分别用于加载系统配置和系统环境变量。详情参考:系统变量之System.getEnv()和System.getProperty()
    如果需要将命令行参数存入Environment配置中,则会解析命令行参数为KV形式,并保存到Environment配置中。
  2. 配置Profiles
    protected void configureProfiles(ConfigurableEnvironment environment, String[] args) {
        environment.getActiveProfiles(); // ensure they are initialized
        // But these ones should go first (last wins in a property key clash)
        Set profiles = new LinkedHashSet<>(this.additionalProfiles);
        profiles.addAll(Arrays.asList(environment.getActiveProfiles()));
        environment.setActiveProfiles(StringUtils.toStringArray(profiles));
    }

第三步:监听回调

在这个过程中,会遍历所有在spring.factories文件中配置的SpringApplicationRunListeners实例,并调用其environmentPrepared方法。
配置文件的加载就是在监听器的回调方法中完成的。

第四步:绑定到SpringApplication

在这个过程中,会将刚才构建好的Environment对象绑定到当前的SpringApplication中。

你可能感兴趣的:(Spring Boot启动-构造容器环境)