03.Spring IoC 容器 - 初始化

基本概念

Spring IoC 容器的初始化过程在监听器 ContextLoaderListener 类中定义。

具体由该类的的 configureAndRefreshWebApplicationContext 方法实现,它包含了两个过程:

  • 配置过程
  • 刷新过程

原理分析

下面来看 configureAndRefreshWebApplicationContext 方法的具体实现:

// 表示容器的标识
public static final String CONTEXT_ID_PARAM = "contextId";

// 表示容器的配置文件路径
public static final String CONFIG_LOCATION_PARAM = "contextConfigLocation";

protected void configureAndRefreshWebApplicationContext(
    ConfigurableWebApplicationContext wac, ServletContext sc) {

    if (ObjectUtils.identityToString(wac).equals(wac.getId())) {

        // 配置过程:

        // 1.设置容器的标识,即 ContextId
        String idParam = sc.getInitParameter(CONTEXT_ID_PARAM);
        if (idParam != null) {
            wac.setId(idParam);
        }else {
            wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + 
                ObjectUtils.getDisplayString(sc.getContextPath()));
        }
    }

    //  2.设置容器的 ServletContext
    wac.setServletContext(sc);

    // 3.设置容器的配置文件路径,即 ContextConfigLocation
    String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);
    if (configLocationParam != null) {
        wac.setConfigLocation(configLocationParam);
    }

    // 4.设置容器的环境,并初始化它的属性 
    ConfigurableEnvironment env = wac.getEnvironment();

    // 5.初始化容器的环境属性
    if (env instanceof ConfigurableWebEnvironment) {
        ((ConfigurableWebEnvironment) env).initPropertySources(sc, null);
    }

    // 自定义过程,暂不探究
    customizeContext(sc, wac);

    // 刷新过程:
    wac.refresh();
}

Spring 容器的初始化过程实际被细分为了两个过程:配置过程、刷新过程

  • 在 ContextLoaderListener 类中主要完成了配置过程,即设置容器的 ContextId,ServletContext,ConfigLocation,ConfigurableEnvironment 属性等。

  • 刷新的过程则由刚刚创建 Spring 容器自己完成。


配置过程

1.设置容器的环境

Spring 容器在设置的它的 Environment 属性时,如果不存在则默认创建一个 StandardServletEnvironment对象。具体的继承关系如下:

这里写图片描述

来看下 getEnvironment 方法:

private ConfigurableEnvironment environment;

public ConfigurableEnvironment getEnvironment() {
    // 不存在,则创建
    if (this.environment == null) {
        this.environment = createEnvironment();
    }
    return this.environment;
}

protected ConfigurableEnvironment createEnvironment() {
    return new StandardServletEnvironment();
}

再来分析 StandardEnvironment 的初始化过程,该类在初始化过程中,会创建一个 propertySources 对象来保存系统相关的环境变量与属性。

// AbstractEnvironment 类
private final MutablePropertySources propertySources = 
    new MutablePropertySources(this.logger);
public AbstractEnvironment() {
    customizePropertySources(this.propertySources);
    // 省略部分代码...
}

// StandardEnvironment 类
public static final String SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME ="systemEnvironment";

public static final String SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME = "systemProperties";

protected void customizePropertySources(MutablePropertySources propertySources) {

    propertySources.addLast(
        new MapPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, 
            getSystemProperties()));

    propertySources.addLast(
        new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, 
            getSystemEnvironment()));
}

2.初始化容器的环境属性

即初始化 Environment 的 propertySources 属性,它会将 ServletContext 、ServletConfig 添加到 
propertySources 中。

// StandardServletEnvironment 类
public void initPropertySources(ServletContext servletContext, 
    ServletConfig servletConfig) {
    // 将 servletContext、servletConfig 添加到 propertySources
    WebApplicationContextUtils.initServletPropertySources(
        getPropertySources(),servletContext, servletConfig);
}
public MutablePropertySources getPropertySources() {
    return this.propertySources;
}
posted @ 2018-07-22 11:50  沫小淘  阅读(263)  评论(0编辑  收藏  举报