Spring中BeanFactory的创建

AbstractApplicationContext类的refresh方法是Spring Framework中的关键核心实现,Spring Framework的源码分析主要就是围绕该函数来进行的。在refresh方法中会调用obtainFreshBeanFactory来创建和刷新BeanFactory,本文就来分析一下这个过程。


refresh方法

首先给出ApplicationContext中的refresh方法代码,本文是在分析该方法中调用的obtainFreshBeanFactory方法,注意和主线结合起来。

java
spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java
@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

        // Prepare this context for refreshing.
        prepareRefresh();

        // Tell the subclass to refresh the internal bean factory.
        /*
         * 通过new DefaultListableBeanFactory()的方式创建容器,
         * 这一步会加载bean的定义
         */
        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.
            // 会注册web作用域
            postProcessBeanFactory(beanFactory);

            StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
            // Invoke factory processors registered as beans in the context.
            /*
             * 执行BeanFactoryPostProcessor
             */
            invokeBeanFactoryPostProcessors(beanFactory);

            // Register bean processors that intercept bean creation.
            /*
             * 往beanPostProcessors属性中add后置处理器并整理好顺序,便于后续执行
             */
            registerBeanPostProcessors(beanFactory);
            beanPostProcess.end();

            // Initialize message source for this context.
            /*
             * 这一步较简单,向容器里注册一个一个事件源的单例Bean:MessageSource
             */
            initMessageSource();

            // Initialize event multicaster for this context.
            /*
             * 初始化Spring的事件多播器:ApplicationEventMulticaster
             */
            initApplicationEventMulticaster();

            // Initialize other special beans in specific context subclasses.
            /*
             * 模板方法,子类会实现
             * 比如在Spring Boot中,会在该方法中创建web服务器
             */
            onRefresh();

            // Check for listener beans and register them.
            /*
             * 注册事件监听器
             */
            registerListeners();

            // Instantiate all remaining (non-lazy-init) singletons.
            /*
             * ---- 极其重要步骤 ----
             * 会实例化单例bean
             */
            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();
            contextRefresh.end();
        }
    }
}

obtainFreshBeanFactory方法中,主要是调用了两个需要子类实现的模板方法。

java
spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    refreshBeanFactory();
    return getBeanFactory();
}
protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;
@Override
public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;

下面分别来看看这两个模板方法。

refreshBeanFactory方法

该方法主要有两个子类实现了:

  • AbstractRefreshableApplicationContext:在传统的Spring + Spring MVC的项目中用的较多,主要包含XmlWebApplicationContextAnnotationConfigWebApplicationContext,一个基于XML配置,一个基于注解配置。
  • GenericApplicationContext:Spring Boot中使用的是这个。

GenericApplicationContext中的实现

java
spring-context/src/main/java/org/springframework/context/support/GenericApplicationContext.java
@Override
protected final void refreshBeanFactory() throws IllegalStateException {
    // CAS设置refreshed为true,表示已刷新
    if (!this.refreshed.compareAndSet(false, true)) {
        throw new IllegalStateException(
                "GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
    }
    // 设置序列化ID
    this.beanFactory.setSerializationId(getId());
}

这里好像并没有做什么重要的操作,实际上在构造函数中就已经创建了BeanFactory

java
spring-context/src/main/java/org/springframework/context/support/GenericApplicationContext.java
public GenericApplicationContext() {
    this.beanFactory = new DefaultListableBeanFactory();
}

AbstractRefreshableApplicationContext中的实现

java
spring-context/src/main/java/org/springframework/context/support/AbstractRefreshableApplicationContext.java
@Override
protected final void refreshBeanFactory() throws BeansException {
    if (hasBeanFactory()) { // 如果已经存在了beanFactory,那么:
        destroyBeans(); // 销户所有的bean
        closeBeanFactory(); // 关闭beanFactory
    }
    try {
        DefaultListableBeanFactory beanFactory = createBeanFactory(); // 注意是DefaultListableBeanFactory,该类是重点
        beanFactory.setSerializationId(getId());
        customizeBeanFactory(beanFactory); // 把旧容器的一些配置赋值给新容器
        /*
         * 加载bean配置信息;模板方法,由子类实现
         * 在AnnotationConfigWebApplicationContext中(基于注解配置的情况),
         * 会创建AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner。
         *
         * AnnotatedBeanDefinitionReader会注册一些BeanFactoryPostProcessor的BeanDefinition,以便后续使用。
         */
        loadBeanDefinitions(beanFactory);
        this.beanFactory = beanFactory;
    }
    catch (IOException ex) {
        throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
    }
}
protected DefaultListableBeanFactory createBeanFactory() {
    return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}
protected abstract void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)
        throws BeansException, IOException;

refreshBeanFactory方法中主要就是做了两件事情。

  • 创建BeanFactory
  • 调用loadBeanDefinitions来加载一些bean定义:该方法是个模板方法,由子类实现。但目前主流使用方式不使用这套逻辑,而且有多种实现,所以本文不分析,后面单独写文章来分析。

getBeanFactory方法

该方法主要是获取上面创建的BeanFacory实例,bean工厂实例没有定义在AbstractApplicationContext类中,而是定义了一个模板方法,由子类来返回对象。

GenericApplicationContext中的实现

这里是直接返回该类定义的属性beanFactory

java
spring-context/src/main/java/org/springframework/context/support/GenericApplicationContext.java
@Override
public final ConfigurableListableBeanFactory getBeanFactory() {
    return this.beanFactory;
}

AbstractRefreshableApplicationContext中的实现

java
spring-context/src/main/java/org/springframework/context/support/AbstractRefreshableApplicationContext.java
@Override
public final ConfigurableListableBeanFactory getBeanFactory() {
    DefaultListableBeanFactory beanFactory = this.beanFactory;
    if (beanFactory == null) {
        throw new IllegalStateException("BeanFactory not initialized or already closed - " +
                "call 'refresh' before accessing beans via the ApplicationContext");
    }
    return beanFactory;
}

这里也是直接返回了本类的属性beanFactory

总结

本文比较简单,主要是分析了BeanFactory的创建过程。主refresh方法中的后续步骤都会基于该bean工厂对象来进行。