Spring IoC初始化流程(一)BeanDefinition加载解析及注册⼦流程

spring-framework版本5.1.x

1.Spring IoC的容器体系

IoC容器是Spring的核⼼模块,是抽象了对象管理、依赖关系管理的框架解决⽅案。Spring 提供了很多 的容器,其中 BeanFactory 是顶层容器(根容器),不能被实例化,它定义了所有 IoC 容器 必须遵从 的⼀套原则,具体的容器实现可以增加额外的功能,⽐如我们常⽤到的ApplicationContext,其下更具 体的实现如 ClassPathXmlApplicationContext 包含了解析 xml 等⼀系列的内容, AnnotationConfigApplicationContext 则是包含了注解解析等⼀系列的内容。Spring IoC 容器继承体系 ⾮常聪明,需要使⽤哪个层次⽤哪个层次即可,不必使⽤功能⼤⽽全的。

BeanFactory顶级接口方法栈如下:

BeanFactory 容器继承体系:

通过其接⼝设计,我们可以看到我们⼀贯使⽤的 ApplicationContext 除了继承BeanFactory的⼦接⼝, 还继承了ResourceLoader、MessageSource等接⼝,因此其提供的功能也就更丰富了。


Spring IoC容器初始化主流程

Spring IoC 容器初始化的关键环节就在 AbstractApplicationContext#refresh() ⽅法中 ,我们查看 refresh ⽅法来俯瞰容器创建的主体流程,主体流程下的具体⼦流程我们后⾯再来讨论。下图是refresh()十大步骤

@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        
    // 第⼀步:刷新前的预处理
    prepareRefresh();
        
     /*
     第⼆步:
     获取BeanFactory;默认实现是DefaultListableBeanFactory
     加载BeanDefition 并注册到 BeanDefitionRegistry
     */
    ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
        
    // 第三步:BeanFactory的预准备⼯作(BeanFactory进⾏⼀些设置,⽐如context的类加载器等)
    prepareBeanFactory(beanFactory);
 
        try {
             // 第四步:BeanFactory准备⼯作完成后进⾏的后置处理⼯作
             postProcessBeanFactory(beanFactory);
            
             // 第五步:实例化并调⽤实现了BeanFactoryPostProcessor接⼝的Bean
             invokeBeanFactoryPostProcessors(beanFactory);
            
             // 第六步:注册BeanPostProcessor(Bean的后置处理器),在创建bean的前后等执⾏
             registerBeanPostProcessors(beanFactory);
            
             // 第七步:初始化MessageSource组件(做国际化功能;消息绑定,消息解析);
             initMessageSource();
            
             // 第⼋步:初始化事件派发器
             initApplicationEventMulticaster();
            
             // 第九步:⼦类重写这个⽅法,在容器刷新的时候可以⾃定义逻辑
             onRefresh();
            
             // 第⼗步:注册应⽤的监听器。就是注册实现了ApplicationListener接⼝的监听器bean
             registerListeners();
            
             /*
             第⼗⼀步:
             初始化所有剩下的⾮懒加载的单例bean
             初始化创建⾮懒加载⽅式的单例Bean实例(未设置属性)
             填充属性
             初始化⽅法调⽤(⽐如调⽤afterPropertiesSet⽅法、init-method⽅法)
             调⽤BeanPostProcessor(后置处理器)对实例bean进⾏后置处
             */
             finishBeanFactoryInitialization(beanFactory);
            
             /*
             第⼗⼆步:
             完成context的刷新。主要是调⽤LifecycleProcessor的onRefresh()⽅法,并且发布事
             件 (ContextRefreshedEvent)
             */
             finishRefresh();
        }
    ......
    }
}

Bean对象创建的⼏个关键时机点代码层级的调⽤都在 AbstractApplicationContext 类 的 refresh() ⽅法中,可⻅这个⽅法对于Spring IoC 容器初始化来说相当 关键

分析BeanFactoryPostProcessor 初始化和调⽤情况

分别在构造函数、postProcessBeanFactory ⽅法处打断点,观察调⽤栈,发现

BeanFactoryPostProcessor 初始化在AbstractApplicationContext类refresh⽅法的 invokeBeanFactoryPostProcessors(beanFactory); postProcessBeanFactory 调⽤在AbstractApplicationContext类refresh⽅法的 invokeBeanFactoryPostProcessors(beanFactory);

分析 BeanPostProcessor 初始化和调⽤情况

分别在构造函数、postProcessBeanFactory ⽅法处打断点,观察调⽤栈,发现

BeanPostProcessor 初始化在AbstractApplicationContext类refresh⽅法的 registerBeanPostProcessors(beanFactory);

postProcessBeforeInitialization 调⽤在AbstractApplicationContext类refresh⽅法的 finishBeanFactoryInitialization(beanFactory); postProcessAfterInitialization 调⽤在AbstractApplicationContext类refresh⽅法的 finishBeanFactoryInitialization(beanFactory);

汇总如下:

关键点 触发代码
构造器 refresh#finishBeanFactoryInitialization(beanFactory)(beanFactory)
BeanFactoryPostProcessor 初始化 refresh#invokeBeanFactoryPostProcessors(beanFactory)
BeanFactoryPostProcessor ⽅法调⽤ refresh#invokeBeanFactoryPostProcessors(beanFactory)
BeanPostProcessor 初始化 registerBeanPostProcessors(beanFactory)
BeanPostProcessor ⽅法调⽤ refresh#finishBeanFactoryInitialization(beanFactory)

BeanFactory创建流程
  • 获取BeanFactory⼦流程
    • 时序图

      AbstractApplicationContext 里面的 refresh() 调用了它里面的 obtainFreshBeanFactory(),进入 obtainFreshBeanFactory() 方法中,调用了AbstractRefreshableApplicationContext 里面的 refreshBeanFactory(),但该方法实际上又调用了 AbstractRefreshableApplicationContext 里面的 createBeanFactory(),接着从 AbstractApplicationContext 调用AbstractRefreshableApplicationContext 中的 getBeanFactory() 方法,并将 DefaultListableBeanFactory 返回 (默认实现的是DefaultListableBeanFactory)

  • BeanDefinition加载解析及注册⼦流程
    1. 该⼦流程涉及到如下⼏个关键步骤

      1. Resource定位:指对BeanDefinition的资源定位过程。通俗讲就是找到定义Javabean信息的XML⽂ 件,并将其封装成Resource对象。

      2. BeanDefinition载⼊ :把⽤户定义好的Javabean表示为IoC容器内部的数据结构,这个容器内部的数据结构就是BeanDefinition。

      注册BeanDefinition到 IoC 容器

    2. 过程分析

      1. ⼦流程⼊⼝在 AbstractRefreshableApplicationContext#refreshBeanFactory ⽅法中

      2. 依次调⽤多个类的 loadBeanDefinitions ⽅法 —> AbstractXmlApplicationContext —> AbstractBeanDefinitionReader —> XmlBeanDefinitionReader ⼀直执⾏到 XmlBeanDefinitionReader 的 doLoadBeanDefinitions ⽅法

      3. 我们重点观察XmlBeanDefinitionReader 类的 registerBeanDefinitions ⽅法,期间产⽣了多 次重载调⽤,我们定位到最后⼀个

        此处我们关注两个地⽅:⼀个createRederContext⽅法,⼀个是 DefaultBeanDefinitionDocumentReader类的registerBeanDefinitions⽅法,先进⼊ createRederContext ⽅法看看

        我们可以看到,此处 Spring ⾸先完成了 NamespaceHandlerResolver 的初始化。 我们再进⼊ registerBeanDefinitions ⽅法中追踪,调⽤了 DefaultBeanDefinitionDocumentReader#registerBeanDefinitions ⽅法

        进⼊ doRegisterBeanDefinitions ⽅法

        进⼊ parseBeanDefinitions ⽅法

        进⼊ parseDefaultElement ⽅法

        进⼊ processBeanDefinition ⽅法

        ⾄此,注册流程结束,我们发现,所谓的注册就是把封装的 XML 中定义的 Bean信息封装为 BeanDefinition 对象之后放⼊⼀个Map中,BeanFactory 是以 Map 的结构组织这些 BeanDefinition 的。

        可以在DefaultListableBeanFactory中看到此Map的定义

        /** Map of bean definition objects, keyed by bean name. */
        private final Map<String, BeanDefinition> beanDefinitionMap = new
        ConcurrentHashMap<>(256);
      4. 时序图