Spring IOC 源码解析二(BeanFactory的创建)

引言

在第二期介绍容器的refresh方法开始之前,首先大家应该对Spring容器的整个继承体系有个大概的了解,不然就会有雾里看花的感觉

  • 为了帮助大家理清整个继承体系,我将接下来所要涉及到的几个重要类及接口的继承关系贴上来,在阅读中如有疑惑的话,可以回过头来看看这几张图
XmlWebApplicationContext

由web容器启动的Spring容器类,注意与DefaultListableBeanFactory的区别

Spring IOC 源码解析二(BeanFactory的创建)_第1张图片
image.png

DefaultListableBeanFactory

实际实现的bean工厂类,获取bean操作的方法都在这里


Spring IOC 源码解析二(BeanFactory的创建)_第2张图片
image.png
XmlBeanDefinitionReader

读取我们配置文件信息


Spring IOC 源码解析二(BeanFactory的创建)_第3张图片
image.png
BeanFactory 接口及其实现

由以上图中可以看出,BeanFactory 接口定义了IOC容器最基本的功能规范,是每一个IOC容器都要遵守的基本规范。其中最重要的就是定义了getBean方法,让我们可以从容器中根据名字拿到所需要的bean。 DefaultListableBeanFactory就是其一个重要实现,与我们接触也是最多的,而XmlWebApplicationContext可以理解为一个更高级的IOC容器,除支持BeanFactory的基本功能外,还提供了很多扩展功能

容器 refresh 方法

接着上节继续往下讲
refresh 是整个容器启动的核心方法,在AbstractApplicationContext中,其做的事情主要有三个:

  • BeanFactory的创建(DefaultListableBeanFactory)
  • BeanDefinition的Resource定位,载入,和注册
  • 在实例化Bean之前对BeanDefinition进行修改(调用实现了接口BeanFactoryPostProcessorBeanDefinitionRegistryPostProcessor的类)
@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // Prepare this context for refreshing.
        prepareRefresh();

        // 创建BeanFactory,并载入BeanDefinitions(重要)
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        // Prepare the bean factory for use in this context.
        prepareBeanFactory(beanFactory);

        try {
            // Allows post-processing of the bean factory in context subclasses.
            postProcessBeanFactory(beanFactory);

            // 执行 BeanFactoryPostProcessors
            invokeBeanFactoryPostProcessors(beanFactory);

            // 注册 BeanPostProcessors
            registerBeanPostProcessors(beanFactory);

            // Initialize message source for this context.
            initMessageSource();

            // Initialize event multicaster for this context.
            initApplicationEventMulticaster();

            // Initialize other special beans in specific context subclasses.
            onRefresh();

            // Check for listener beans and register them.
            registerListeners();

            // 提前实例化化全部延迟加载的单例类型
            finishBeanFactoryInitialization(beanFactory);

            // Last step: publish corresponding event.
            finishRefresh();
        }

        catch (BeansException ex) {
            if (logger.isWarnEnabled()) {
                logger.warn("Exception encountered during context initialization - " +
                        "cancelling refresh attempt: " + ex);
            }

            // Destroy already created singletons to avoid dangling resources.
            destroyBeans();

            // Reset 'active' flag.
            cancelRefresh(ex);

            // Propagate exception to caller.
            throw ex;
        }

        finally {
            // Reset common introspection caches in Spring's core, since we
            // might not ever need metadata for singleton beans anymore...
            resetCommonCaches();
        }
    }
}

obtainFreshBeanFactory()

obtainFreshBeanFactory() 也在 AbstractApplicationContext类中,主要逻辑在refreshBeanFactory 方法中

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    refreshBeanFactory();
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (logger.isDebugEnabled()) {
        logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
    }
    return beanFactory;
}

refreshBeanFactory() (AbstractRefreshableApplicationContext)

这里做的事情主要有2个:

1.创建BeanFactory (createBeanFactory())
2.载入BeanDefinitions (loadBeanDefinitions(beanFactory))

protected final void refreshBeanFactory() throws BeansException {
    if (hasBeanFactory()) {
        destroyBeans();
        closeBeanFactory();
    }
    try {
        DefaultListableBeanFactory beanFactory = createBeanFactory();
        beanFactory.setSerializationId(getId());
        customizeBeanFactory(beanFactory);
        loadBeanDefinitions(beanFactory);
        synchronized (this.beanFactoryMonitor) {
            this.beanFactory = beanFactory;
        }
    }
    catch (IOException ex) {
        throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
    }
}

createBeanFactory()

从这里可以知道容器所使用的BeanFactory实现类是 DefaultListableBeanFactory

protected DefaultListableBeanFactory createBeanFactory() {
    return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}

loadBeanDefinitions(beanFactory) (XmlWebApplicationContext)

这个方法是在XmlWebApplicationContext实现的,Spring随处可见父类调用子类的设计模式(模板方法设计模式)

在解析loadBeanDefinitions方法之前,有必要先了解BeanDefinition在Spring中所表示的概念 (通俗的理解可以说是bean的抽象数据结构,它包括属性参数,构造器参数,以及其他具体的参数,就是我们从配置信息中读出来Bean的抽象数据结构)有兴趣的可以去看看BeanDefinition的数据结构。

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
    // 创建一个XmlBeanDefinitionReader,用来读取配置文件配置的Bean信息,解析成beanDefinition,并配置beanFactory 方便回调
    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

    // 配置XmlBeanDefinitionReader的一些基本配置
    beanDefinitionReader.setEnvironment(getEnvironment());
    // 配置ResourceLoader(XmlWebApplicationContext 是实现了ResourceLoader接口的,不清楚的可以上图的继承链)
    beanDefinitionReader.setResourceLoader(this);
    beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

    // Allow a subclass to provide custom initialization of the reader,
    // 这里没做任何事情
    initBeanDefinitionReader(beanDefinitionReader);
    loadBeanDefinitions(beanDefinitionReader);
}

loadBeanDefinitions(XmlBeanDefinitionReader reader)

XmlBeanDefinitionReader 根据配置文件位置调用 loadBeanDefinitions

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {
    String[] configLocations = getConfigLocations();
    if (configLocations != null) {
        for (String configLocation : configLocations) {
            reader.loadBeanDefinitions(configLocation);
        }
    }
}

尾言

到目前为止,我们知道了IOC容器的创建,以及BeanDefinition是在哪里被加载的。接下来要讲的自然就是配置信息是如何被解析加载的,以及如何注册进BeanFactory的。see => 下期

博客原文地址戳这里

Spring 系列

  • Spring-源码解析一(IOC容器的创建)

  • Spring 源码解析二(BeanFactory的创建)

  • Spring 源码解析三(BeanDefinitions的载入注册)

  • Spring IOC 源码解析四(加载非延迟单例前的操作)

  • Spring IOC 源码解析五(非延迟加载bean的初始化)

  • Spring AOP 源码解析一 (AOP入口浅谈)

  • Spring AOP 源码解析二 (AOP核心概念及接口分析)

  • Spring AOP 源码解析三(代理对象的创建)

  • Spring IOC 源码解析 (循环依赖的解决)

你可能感兴趣的:(Spring IOC 源码解析二(BeanFactory的创建))