厚积薄发打卡Day81 :【MSUP】必会技术框架Spring(下)<从Spring初始化流程到SpringBoot>

前言

在看狂神频道的时候偶然发现下图,感触颇深。特别在当今【程序 = 业务 + 框架】思想盛行的开发者中,夯实基础基础显得格外重要,因此开此专栏总结记录。
厚积薄发打卡Day81 :【MSUP】必会技术框架Spring(下)<从Spring初始化流程到SpringBoot>

对于Spring框架的知识,已经在学习设计模式的时候练习过一轮,接下来不断温故而知新哈哈,学习记录回顾:

  1. 厚积薄发打卡Day47: [itcast] GoF23设计模式之<自定义SpringIOC>(上)
  2. 厚积薄发打卡Day48: [itcast] GoF23设计模式之<自定义SpringIOC>(下)

SpringContext初始化流程:(需阅读源码)

详见:

  1. Spring核心 ApplicationContext的加载过程
  2. 理解Spring容器、BeanFactory和ApplicationContext

厚积薄发打卡Day81 :【MSUP】必会技术框架Spring(下)<从Spring初始化流程到SpringBoot>

  • 左上角是三种类型的context:

    • ClassPathXmlApplicationContext
    • SpringApplicationContext
    • WebApplicationContext

    厚积薄发打卡Day81 :【MSUP】必会技术框架Spring(下)<从Spring初始化流程到SpringBoot>

  • 不论哪种context创建后都会调用AbstractApplicationContext 类的refresh 方法,这个方法是我们要重点分析的,在refresh 方法中:

    @Override
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            prepareRefresh();
            // Tell the subclass to refresh the internal BeanFactroy.
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
            // Prepare the BeanFactroy for use in this context.
            prepareBeanFactory(beanFactory);
            try {
                // Allows post-processing of the BeanFactroy in context subclasses.
                postProcessBeanFactory(beanFactory);
                // Invoke factory processors registered as beans in the context.
                invokeBeanFactoryPostProcessors(beanFactory);
                // Register bean processors that intercept bean creation.
                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();
                // 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...
               ;
            }
        }
    }
    
    • 第一步,prepareRefresh();
      • 首先对刷新进行准备,包括设置开始时间,设置激活状态,初始化context 环境中的占位符,这个动作根据子类的需求由子类来执行,然后验证是否缺失必要的properties
    • 第二步,ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
      • 刷新并获取内部的beanFactory
    • 第三步,prepareBeanFactory(beanFactory) 对Beanfactory 进行准备工作,
      • 比如设置类加载器和后置处理器,配置不能自动装配的类型,注册默认的环境Bean
    • 第四步,postProcessBeanFactory(beanFactory); 为context 的子类提供后置处理并factory 的扩展能力,
      • 如果子类想在并定义加载完成后,开始初始化上下文之前做一些特殊逻辑,可以复写这个方法
    • 第五步,invokeBeanFactoryPostProcessors(beanFactory) 执行context 中注册的BeanFactroy 后置处理器,这里有两种后置处理器:
      • 一种是可以注册bean 的后置处理器
      • 另一种是针对BeanFactroy 进行处理的后置处理器
      • 执行的顺序是先按优先级执行可注册并的处理器,然后再按优先级执行针对BeanFactroy 的处理器
      • 对SpringBoot来说这一步会进行注解bean definition 的解析,流程如右面的小框中所示
      • 由configuration class post processor 出发由classpathbeandefinitionscanner解析bean 注册到BeanFactroy
    • 第六步,registerBeanPostProcessors(beanFactory);
      • 按优先级顺序在BeanFactroy 中注册bean 的后置处理器,Bean后置处理器可以在Bean的初始化前后执行处理
    • 第七步,initMessageSource();
      • 初始化消息源,消息源用来支持消息的国际化
    • 第八步,initApplicationEventMulticaster();
      • 初始化应用事件广播器。事件广播器用来向application listener 通知各种应用产生的事件,是一个标准的观察者模式
    • 第九步,onRefresh();
      • 是留给子类的扩展步骤,用来让特定的context 子类来初始化其他的Bean
    • 第十步,registerListeners();
      • 把实现的application listener 的bean 注册到事件广播器,并对广播器中早期没有广播的事件进行通知
    • 第十一步,finishBeanFactorylnitialization(beanFactory);
      • 冻结所有的Bean人描述信息的修改实例化非延迟加载的单例Bean
    • 第十二步,finishRefresh();
      • 完成上下文的刷新工作,调用LifecycleProcessor 的on fresh 方法,以及发布context refresh 的event事件
    • 最后在finally 中执行第十三步,resetCommonCaches() 重置公共的缓存,
      • 比如ReflectionUtils中的缓存AnnotationUtils中的缓存等等
    • 至此,spring 的context 初始化就完成了,由于篇幅和时间的关系呢,这里介绍了最主要的流程,建议课后阅读源码来复习这个知识点,来补全细节

Spring中Bean生命周期:(需阅读源码)

厚积薄发打卡Day81 :【MSUP】必会技术框架Spring(下)<从Spring初始化流程到SpringBoot>

面试中经常会问到Bean人的生命周期,我们先看绿色的部分:

  • Bean的创建过程:
    • 首先调用Bean的构造方法创建bean,然后通过反射调用setter 方法进行属性的依赖注入,
    • 第三步,如果实现了BeanNameAware接口的话,会设置Bean the name
    • 第四步,如果实现了BeanfactoryAware接口,会把Beanfactory 设置给bean
    • 第五步,如果实现ApplicationContextAware接口会给bean 设置application context
    • 第六步,如果实现了BeanPostProcessor 接口,则执行前置的处理方法
    • 第七步,实现了initialize bean 接口的话会执行after property set方法
    • 第八步,执行自定义的init的方法
    • 第九步,执行bean post processor 接口的后置处理方法
  • 这时就完成了bean 的创建过程,那么在使用完bean 需要销毁的时候,会先执行disposable bean 接口的destroy 方法
  • 然后再执行自定义的destroy 方法

这部分也建议你阅读源码来加深理解

Spring扩展接口:

这一页介绍对spring 进行定制化功能扩展时,可以选择的一些扩展点:

厚积薄发打卡Day81 :【MSUP】必会技术框架Spring(下)<从Spring初始化流程到SpringBoot>

  • BeanFactoryPostProcessor是Beanfactory 的后置处理器
    • 支持在Beanfactory 标准初始化完成后,对并factory 进行一些额外处理
    • 我们在讲context 初始化流程时介绍过这,这时所有的Bean的描述信息已经加载完毕
    • 但是还没有进行Bean的初始化,例如,我前面提到的property placeholder configure 就是在这个扩展点上对bean 属性中的站位服务进行替换的
  • BeanDefinitionRegistryPostProcessor
    • 它扩展自BeanPostProcessor,在执行BeanPostProcessor的功能前提供了可以添加并定义的能力
    • 允许在初始化一般的Bean前注册额外的Bean
    • 例如可以在这里根据Bean的scope 创建一个新的代理Bean
  • BeanPostProcessor
    • 提供了在bean 初始化的之前和之后,插入自定义逻辑的能力
    • 与BeanFactoryPostProcessor的区别主要是处理对象不同,BeanFactoryPostProcessor是Beanfactory 进行处理
    • BeaPostProcessor是对Bean进行处理
  • 上面这三个扩展点可以通过实现ordered 或者priority ordered 接口来指定执行顺序,实现priority order 接口的processor 会先于实行order 接口的执行
  • ApplicationContextAware
    • 可以获得application context,以及其中的Bean当需要在代码中动态获取Bean时,可以通过实现这个接口来实现
  • InitializingBean
    • 可以在bean 初始化完成,所有属性设置完成后执行特定的逻辑
    • 例如对自动装配的属性进行验证等等
  • DisposableBean
    • 用于在并销毁前执行特定的逻辑
    • 例如做一些回收工作等等
  • ApplicationListener
    • 用来监听spring 的标准事件以及自定义的事件

SpringBoot扩展:

厚积薄发打卡Day81 :【MSUP】必会技术框架Spring(下)<从Spring初始化流程到SpringBoot>

  • SpringBoot启动流程:

    • 首先要配置environment
    • 然后准备context 上下文
    • 包括执行application context 的后置处理器
    • 初始化initialize,通知listener 处理context prepared 和contextloaded 事件
    • 最后执行refresh context
    • 也就是我们前面介绍过的AbstractApplicationContext 类的refresh 方法
  • SpringBoot中有两种上下文:

    • 一种是bootstrap
      • bootstrap 是应用程序的父上下文,也就是说bootstrap 会先于application 加载
      • bootstrap 主要用于从额外的资源来加载配置信息,还可以从本地外部配置文件中解密属性
      • bootstrap 里面的属性会优先加载,默认也不能被本地相同的配置覆盖
    • 另一种是application
  • Springboot 的注解

    • 需要知道 SpringBootApplication,包含了三个注解:

      •   @SpringBootConfiguration
        
      •   @EnableAutoConfiguration
        
      •   @ComponentScan
        

      厚积薄发打卡Day81 :【MSUP】必会技术框架Spring(下)<从Spring初始化流程到SpringBoot>

    • @SpringBootConfiguration注解里面包含了configuration 注解,也就是SpringBoot的自动配置功能
      厚积薄发打卡Day81 :【MSUP】必会技术框架Spring(下)<从Spring初始化流程到SpringBoot>

    • conditional 注解是控制自动配置的生效条件的注解

      • 例如bean 或class 的存在或不存在时进行配置,当满足条件时进行配置等等
  • SpringBoot的几个特色模块:

    • starter 是SpringBoot提供的无缝集成功能的一种方式,使用某个功能时,开发者不需要关注各种依赖库的处理,不需要具体的配置信息,由SpringBoot的自动配置进行bean 的创建:
      • 例如需要使用web 功能时,只需要在依赖中引入SpringBootstarter web 即可
    • actuator 是用来对应用程序进行监控和管理,通过restful API 请求,来监管审计,收集应用的运行情况
      提供了一系列开发工具的支持来提高开发效率,
      • 例如热部署能力等等
    • cli 就是命令行接口,是一个命令行工具,支持使用groovy脚本,可以快速搭建spring 原型项目
上一篇:2021-09-08


下一篇:Spring详解,底层原理深入探究(2)