Spring源码速记 - 容器启动过程

149 阅读4分钟

这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战

这类面试八股文,即使看完了源码,不自己再去总结和记忆,时间长了相当于没看。即使Spring的很多知识点都懂了,但是面试真正需要答的顺溜,还是需要能记忆下一些重要梗概。

  1. 容器对象构造:我们创建一个容器,比如ApplicationContext这样的容器对象的时候内部构造会去调用refresh方法。整个容器启动的过程其实也就是refresh的流程。(这个refresh主要是一个模板方法模式)

  2. 创建并初始化BeanFactory容器对象(1. 直接new 2. 设置一些默认值 3. 执行容器定制化钩子逻辑):

    • 然后会通过调用obtainFreshBeanFactory方法创建好BeanFactory对象:DefaultListableBeanFactory。此时BeanFactory对象都是默认(空的)配置,什么都还没有设置。
    • 接着会调用prepareBeanFactory方法对BeanFactory对象做一些初始化工作。此时BeanFactory对象算是创建完成了。
    • 接着会调用一个钩子方法postProcessBeanFactory,让我们容器实现类自己定制BeanFactory对象(如果需要的话)。
  3. 执行BeanFactoryPostProcessor的方法。上面在BeanFactory对象创建完成之后,就需要执行BeanFactory的所有的后处理器。

    • 因为工程中可能存在一些对BeanDefinition的定制化修改,或者动态添加一些BeanDefinition什么的需求,所以在BeanFactory对象创建完成后,需要执行相应的一系列后置处理器。
    • 这部分实现都是通过BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor这2个接口来实现的。
    • 先执行BeanDefinitionRegistryPostProcessor实现类的对应方法。 毕竟BeanDefinition相关的操作优先级更高。
    • 再执行BeanFactoryPostProcessor的方法。
  4. 获取所有的 BeanPostProcessor 注册到BeanFactory中

    • 调用registerBeanPostProcessors,会拿到所有的 BeanPostProcessor 按照一定的优先级注册到BeanFactory对象中(内部有个List存储所有的BeanPostProcessors)。
  5. 执行initMessageSource(国际化),主要作用是初始化国际化配置文件。国际化就是不同国家,显示不同的文字这类的。

  6. 执行 initApplicationEventMulticaster&registerListeners(初始化事件广播器以及注册监听器

    • Spring 事件机制(观察者模式)
      • 即Spring提供了一种机制,让Bean之间可以实现一种发布订阅者模式的机制。
      • 比如下了一个订单成功操作,(此时需要通知物流,发短信等等,后期可能会不断扩展一些新的处理逻辑)如果通过事件机制,我们就不需要都写在下单的service里面。而是往容器注入若干个监听器,然后下单service只需要发送一个下单成功消息即可。
      • 参考:zhuanlan.zhihu.com/p/101128672
  7. 执行finishBeanFactoryInitialization 初始化所有剩下的非懒加载的单实例bean放入到bean缓存中(就是项目中我们注册的那些普通bean)

    • 该方法或拿到容器中所有的BeanDefinition来创建bean对象,创建包括普通bean和FactoryBean对象。
    • Bean的创建流程(很重要-IOC.AOP.生命周期等都和这个有关)
      • 整体上分为3大块:bean的实例化(构造函数),bean属性填充,bean的初始化方法调用
        1. 先从缓存(singletonObjects这个map)中去拿,拿不到再创建。创建之前会先检查是否有dependOn依赖的bean,如果有就先去加载这些bean。
        2. 实例化:通过createBeanInstance 会通过反射来创建bean实例(是一个空的实例,半成品bean)
        3. 属性填充:执行populateBean 方法对属性进行赋值,这个会先调用InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation和postProcessPropertyValues方法。然后applyPropertyValues通过反射去对属性进行赋值。
        4. 初始化方法调用:执行initializeBean 对bean进行初始化工作(最核心的步骤--设计AOP)
          • 如果bean实现了aware接口的话,先执行aware接口方法。注入需要的组件。
          • 执行所有的bean后置处理器的postProcessBeforeInitialization
          • 执行bean的初始化方法,指的是如实现InitializingBean接口或者注解@ PostConstruct方法定义的初始化方法。
          • 执行所有的bean后置处理器的postProcessAfterInitialization
        5. 注册bean的销毁方法
        6. 然后将bean放入内部缓存map中
  8. bean创建完了,之后就是一些收尾工作,比如事件发布等等