04.Spring Ioc 容器

基本概念

Spring Ioc 容器被创建之后,接下来就是它的初始化过程了。该过程包含了配置、刷新两个步骤 

刷新由 Spring 容器自己实现,具体发生在 ConfigurableApplicationContext 的 refresh 方法中。

首先来看该接口的继承关系:

Alt text

由于这里 Spring 的配置文件采用 xml 形式,所以 Ioc 容器的类型默认为 XmlWebApplicationContext。接下来就以该类的 refresh 方法为入口,探究下 Ioc 容器的刷新过程。


原理分析

该类的 refresh 方法继承自己父类 AbstractApplicationContext,观察代码可以发现该方法包含了众多方法,这里只探究下 1、2 过程。

private final Object startupShutdownMonitor = new Object();

public void refresh() throws BeansException, IllegalStateException {
    // 加锁
    synchronized (this.startupShutdownMonitor) {
        // 1.准备刷新
        prepareRefresh();

        // 2.创建内部容器,该容器负责 Bean 的创建与管理 
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        prepareBeanFactory(beanFactory);

        try {
            postProcessBeanFactory(beanFactory);

            invokeBeanFactoryPostProcessors(beanFactory);

            registerBeanPostProcessors(beanFactory);

            initMessageSource();

            initApplicationEventMulticaster();

            onRefresh();

            registerListeners();

            finishBeanFactoryInitialization(beanFactory);

            finishRefresh();

        } catch (BeansException ex) {
            // 省略代码...

            destroyBeans();

            cancelRefresh(ex);

            throw ex;

        } finally {
            resetCommonCaches();
        }
    }
}

准备刷新

初始化准备,即为 Ioc 容器的初始化过程做准备,该过程与 Spring 的 Environment 有关,这里暂不探究。

// 容器早期发布事件集
private Set<ApplicationEvent> earlyApplicationEvents;

protected void prepareRefresh() {
    // 省略部分代码...

    // 1.激活容器
    this.active.set(true);

    // 2.初始化 Environment 的 propertySources 属性 
    initPropertySources();

    // 3.校验 Environment 的 requiredProperties 是否都存在
    getEnvironment().validateRequiredProperties();

    // 4.创建事件集合
    this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}

来看下 initPropertySources 这个方法, 它与 Spring 容器的 Environment 有关:

protected void initPropertySources() {
    // 取得配置过程中创建的容器环境
    ConfigurableEnvironment env = getEnvironment();

    // 初始化 Environment 的 propertySources 属性
    if (env instanceof ConfigurableWebEnvironment) {
        ((ConfigurableWebEnvironment) env).
            initPropertySources(this.servletContext, this.servletConfig);
    }
}

创建内部容器

之前介绍过 ApplicationContext 对象里面会包含了一个 BeanFactory 对象。有关 Bean 的基本功能是调用内部的 BeanFactory 对象来实现的。

在这里, BeanFactory 具体指的是 ConfigurableListableBeanFactory ,来看它们的继承关系:

Alt text


下面来看 obtainFreshBeanFactory 的具体实现:

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {

    // 1.刷新 BeanFactory
    refreshBeanFactory();

    // 2.取得 BeanFactory
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();

    // 省略部分代码...

    return beanFactory;
}

1.刷新 BeanFactory

下面来看刷新内部 BeanFactory 的实现过程:

protected final void refreshBeanFactory() throws BeansException {

    // 1.判断是否存在 Beanfactory ,存在则销毁并关闭它
    if (hasBeanFactory()) {
        destroyBeans();
        closeBeanFactory();
    }

    try {
        // 2.创建 BeanFactory
        DefaultListableBeanFactory beanFactory = createBeanFactory();

        // 3.设置 BeanFactory 的 id,同它外部的 Spring 容器一致
        beanFactory.setSerializationId(getId());

        // 4.定制 BeanFactory 初始化,暂不探究
        customizeBeanFactory(beanFactory);

        // 5.加载 Bean 实例
        loadBeanDefinitions(beanFactory);

        // 6.将 BeanFactory 设置为 Spring 容器的内部 BeanFactory 
        synchronized (this.beanFactoryMonitor) {
            this.beanFactory = beanFactory;
        }

    }catch (IOException ex) {
        // 抛出异常...
    }
}

①判断是否存在 BeanFactory,存在则销毁、关闭容器的内部 BeanFactory

// 1.判断是否存在存在内部 BeanFactory
protected final boolean hasBeanFactory() {
    synchronized (this.beanFactoryMonitor) {
        return (this.beanFactory != null);
    }
}

// 2.若存在销毁内部 BeanFactory 的所有 Bean 
protected void destroyBeans() {
    getBeanFactory().destroySingletons();
}

// 2.关闭 内部 BeanFactory 
protected final void closeBeanFactory() {
    synchronized (this.beanFactoryMonitor) {
        this.beanFactory.setSerializationId(null);
        this.beanFactory = null;
    }
}

②创建 BeanFactory,这里会默认创建 DefaultListableBeanFactory 类作为内部容器(内部 BeanFactory)。

protected DefaultListableBeanFactory createBeanFactory() {
    // 1.取得内部 BeanFactory 的父容器 
    // 2.创建内部 BeanFactory
    return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}


protected BeanFactory getInternalParentBeanFactory() {
    // 判断取得 Spring 容器的父容器类型
    // 匹配,则返回父容器内部 BeanFactory,否则返回父容器
    return (getParent() instanceof ConfigurableApplicationContext) ?
        ((ConfigurableApplicationContext) getParent()).getBeanFactory() :getParent();
}


public DefaultListableBeanFactory(BeanFactory parentBeanFactory) {
    super(parentBeanFactory);
}
public AbstractAutowireCapableBeanFactory(BeanFactory parentBeanFactory) {
    this();
    setParentBeanFactory(parentBeanFactory);
}

Alt text


③加载 Bean 实例,该过程由 BeanDefinitionReader 负责,下篇在详细分析。


2.取得 BeanFactory

// 取得 BeanFactory
public final ConfigurableListableBeanFactory getBeanFactory() {
    synchronized (this.beanFactoryMonitor) {
        if (this.beanFactory == null) {
            // 抛出异常...
        }
        return this.beanFactory;
    }
}

总结

下面通过流程图来总结下 Spring Ioc 容器的初始化过程:

Alt text

原文地址:https://www.cnblogs.com/moxiaotao/p/9349506.html