Spring 源码解析 | 容器初始化 refresh() 分析

863 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

前言:本文主要是讲 Spring 容器的启动过程主要是以题干的方式进行可能不回涉及过多的细节,希望大家阅读本文能对 Spring 容器初始化过程有一个简单的了解。 环境介绍:

  • Spring 5.3.10
  • Jdk 11

创建 Spring 容器

我们创建 Spring 容器可以通过一行代码进行创建

AnnotationConfigApplicationContext applicationContext = 
    new AnnotationConfigApplicationContext(AppConfig.class);

在这个过程中核心就是调用 AnnotationConfigApplicationContext 的构造方法

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
    this();
    register(componentClasses);
    // 刷新上下文
    refresh();
}

Spring 容器创建过程 refresh 方法分析

Spring 容器创建过程主要就是调用 refresh() 方法。我们先一起看看 refresh() 方法具体做了哪些事。具体分为一下几个步骤:

  1. prepareRefresh 预刷新方法,主要是用来初始化和读取上下文配置信息;
  2. obtainFreshBeanFactory() 创建 BeanFactory 对象,其实就是创建一个 Bean 工厂;
  3. prepareBeanFactory(beanFactory) 配置 Bean 工厂,比如设置 ClassLoader、BeanPostProcessor 等;
  4. postProcessBeanFactory 允许子类进行拓展;
  5. invokeBeanFactoryPostProcessors 实例化并调用所有已注册的 BeanFactoryPostProcessor 。调用 BeanFactoryPostProcessor 需要按照顺序调用,优先级是a. 实现 _PriorityOrdered_ 接口;b. 实现 Order 接口; c. 默认。
  6. registerBeanPostProcessors 注册 Bean 对象的 BeanPostProcessors
  7. initMessageSource 初始化 messageSource 其实就是为了支持国际化;
  8. initApplicationEventMulticaster 初始化事件发布器;
  9. onRefresh 模板方法,可以给子类实现,以完成特殊的处理
  10. registerListeners 注册事件监听器,Spring 中的事件机制,其实就是一个典型的观察者模式,这里其实就是注册观察者。
  11. finishBeanFactoryInitialization 完成初始化单实例的非懒加载的 Bean 对象,这里非常关键,对于 Bean 的初始化,属性填充,Aop 等都可以跟着这个方法找到。
  12. finishRefresh完成初始化,这里会发布一个 ContextRefreshedEvent 容器初始化完成事件,以及做一些其他的处理。

对这个过程我们又一个大概的了解过后,我们再来看看 refresh() 方法的定义:

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.
        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);

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

            // Register bean processors that intercept bean creation.
            registerBeanPostProcessors(beanFactory);
            beanPostProcess.end();

            // 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();

            // Instantiate all remaining (non-lazy-init) singletons.
            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();
        }
    }
}

参考文档