20、Spring 应用上下文生命周期.md 15 KB

第二十章:Spring 应用上下文生命周期

ApplicationContext 接口继承关系

img

Spring 应用上下文生命周期

  • AbstractApplicationContext#refresh
  @Override
  public void refresh() throws BeansException, IllegalStateException {
      synchronized (this.startupShutdownMonitor) {
          // 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);
  
              // 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...
              resetCommonCaches();
          }
      }
  }

Spring 应用上下文启动准备阶段

  • AbstractApplicationContext#prepareRefresh() 方法
    • 启动时间 - startupDate
    • 状态标识 - closed(false)active(true)
    • 初始化 PropertySources - initPropertySources()
    • 默认为空方法,子类可继承
    • Web 应用上下文继承这个方法,并将 Web 参数初始化为 PropertySource
    • 检验 Environment 中必须属性
    • AbstractPropertyResolver#requiredProperties,默认为空,可设置
    • 初始化事件监听器集合
    • earlyApplicationListeners
    • applicationListeners
    • 初始化早期 Spring 事件集合
    • earlyApplicationEvents

BeanFactory 创建阶段

  • AbstractApplicationContext#obtainFreshBeanFactory 方法
    • 抽象方法
    • 子类实现,AbstractRefreshableApplicationContext#refreshBeanFactory
    • 刷新 Spring 应用上下文底层 BeanFactory - refreshBeanFactory()
      • 销毁或关闭 BeanFactory ,如果已存在的话
      • 创建 BeanFactory - createBeanFactory()
      • DefaultListableBeanFactory
      • 设置 BeanFactory Id
      • 自定义 BeanFactory 属性 - customizeBeanFactory(beanFactory)
      • 设置 “是否允许 BeanDefinition 重复定义” - customizeBeanFactory(DefaultListableBeanFactory)
      • AbstractRefreshableApplicationContext#allowBeanDefinitionOverriding
      • 默认为 true
      • 设置 “是否允许循环引用(依赖)” - customizeBeanFactory(DefaultListableBeanFactory)
        • AbstractRefreshableApplicationContext#allowCircularReferences
        • 默认为 true
      • 加载 BeanDefinition - loadBeanDefinitions(DefaultListableBeanFactory) 方法
      • 抽象方法
      • 关联新建 BeanFactory 到 Spring 应用上下文
  • 返回 Spring 应用上下文底层 BeanFactory - getBeanFactory()
    • 抽象方法

BeanFactory 准备阶段

  • AbstractApplicationContext#prepareBeanFactory(ConfigurableListableBeanFactory) 方法

    • 关联 ClassLoader

    • 设置 Bean 表达式处理器

    • 与 SpEL 表达式相关

    • org.springframework.context.expression.StandardBeanExpressionResolver

    • 添加 PropertyEditorRegistrar 实现 - ResourceEditorRegistrar

    • org.springframework.beans.support.ResourceEditorRegistrar

    • 添加 Aware 回调接口 BeanPostProcessor 实现 - ApplicationContextAwareProcessor

    • EnvironmentAware

    • EmbeddedValueResolverAware

    • ResourceLoaderAware

    • ApplicationEventPublisherAware

    • MessageSourceAware

    • ApplicationContextAware

    • 忽略 Aware 回调接口作为依赖注入接口

    • 注册 ResolvableDependency 对象 - BeanFactory 、ResourceLoader 、 ApplicationEventPublisher 以及 Applicationcontext

    • BeanFactoryApplicationContext 关联的 BeanFactory

    • ResourceLoaderApplicationEventPublisher 以及 Applicationcontext 都是 ApplicationContext

    • 添加 BeanPostProcessor - ApplicationListenerDetector

    • BeanPostProcessor#postProcessAfterInitialization 阶段,将单例的 ApplicationListener 加入 ApplicationContext

    • 如果包含 beanName 是 loadTimeWeaver 的 bean,注册 BeanPostProcessor - LoadTimeWeaverAwareProcessor 对象,并设置容器的临时 ClassLoader

    ,AbstractBeanFactory#tempClassLoader

    • 与 AOP 相关

    • 注册单例对象 - Environment、Java System Properties 以及 OS 环境变量

    • environment - ApplicationContext#environment

    • systemProperties - (Map) System.getProperties()

    • systemEnvironment - (Map) System.getenv()

BeanFactory后置处理阶段

  • AbstractApplicationContext#postProcessBeanFactory(ConfigurableListableBeanFactory) 方法

    • 由子类覆盖该方法
  • org.springframework.context.support.AbstractApplicationContext#invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory) 方法

    • 判断 BeanFactory 是不是 BeanDefinitionRegistry 的实例

    • DefaultListableBeanFactory 实现 BeanDefinitionRegistry

    • 如果是,调用 BeanFactoryPostProcessor 或 BeanDefinitionRegistryPostProcessor 后置处理方法

      • BeanDefinitionRegistryPostProcessor 继承 BeanFactoryPostProcessor
      • BeanFactoryPostProcessor#postProcessBeanFactory
      • BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry
    • 如果不是,只调用 BeanFactoryPostProcessor 后置处理方法 BeanFactoryPostProcessor#postProcessBeanFactory

    • 如果包含 beanName 是 loadTimeWeaver 的 bean,注册 BeanPostProcessor - LoadTimeWeaverAwareProcessor 对象,并设置容器的临时 ClassLoader

    ,AbstractBeanFactory#tempClassLoader

    • 与 AOP 相关

执行顺序:

  1. 对 BeanDefinitionRegistryPostProcessor 进行处理
    1. 执行 BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry
      1. 按照添加顺序执行, AbstractApplicationContext#beanFactoryPostProcessors 中的 BeanDefinitionRegistryPostProcessor
      2. 按照 Order 顺序执行,BeanFactory 中实现了 PriorityOrderedBeanDefinitionRegistryPostProcessor Bean
      3. 按照 Order 顺序执行,BeanFactory 中实现了 OrderedBeanDefinitionRegistryPostProcessor Bean
      4. 按照 Order 顺序执行,其他 BeanFactory 中的 BeanDefinitionRegistryPostProcessor Bean
    2. 执行 BeanFactoryPostProcessor#postProcessBeanFactory
      1. AbstractApplicationContext#beanFactoryPostProcessors 中的普通 BeanFactoryPostProcessor
      2. BeanFactoryBeanDefinitionRegistryPostProcessor
  2. 对 BeanFactoryPostProcessor 继续处理,BeanFactoryPostProcessor#postProcessBeanFactory
    1. 按照 Order 顺序执行,实现 PriorityOrdered 接口的 BeanFactoryPostProcessor
    2. 按照 Order 顺序执行,实现 Ordered 接口的 BeanFactoryPostProcessor
    3. 其他常规 BeanFactoryPostProcessor

BeanFactory 注册 BeanPostProcessor 阶段

  • AbstractApplicationContext#registerBeanPostProcessors(ConfigurableListableBeanFactory) 方法
    • 注册 PriorityOrdered 类型的 BeanPostProcessor Beans -- 该bean会提前初始化
    • 注册 Ordered 类型的 BeanPostProcessor Beans
    • 注册普通 BeanPostProcessor Beans
    • 注册 MergedBeanDefinitionPostProcessor Beans
    • MergedBeanDefinitionPostProcessor 继承 BeanPostProcessor,生命周期在 MergedBeanDefinition 后
    • 重新注册 ApplicationListenerDetector 对象
    • 为了将 ApplicationListenerDetector 的顺序放到最后

初始化內建 Bean: MessageSource

  • AbstractApplicationContext#initMessageSource 方法
    • 如果 BeanFactory 中存在 beanName 为 messageSourceMessageSource ,则使用,否则注册 DelegatingMessageSource
    • 回顾章节 - 第十二章 Spring 国际化 - MessageSource 内建依赖

初始化內建 Bean: Spring 事件广播器

  • AbstractApplicationContext#initApplicationEventMulticaster 方法
    • 如果 BeanFactory 中存在 beanName 为 applicationEventMulticasterApplicationEventMulticaster ,则使用,否则注册 SimpleApplicationEventMulticaster
    • 回顾章节 - 第十七章 Spring 事件 - ApplicationEventPublisher 底层实现

Spring 应用上下文刷新阶段

  • AbstractApplicationContext#onRefresh 方法
    • 空方法,由子类覆盖该方法
    • org.springframework.web.context.support.AbstractRefreshableWebApplicationContext#onRefresh
    • org.springframework.web.context.support.GenericWebApplicationContext#onRefresh
    • org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext#onRefresh
    • org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#onRefresh
    • org.springframework.web.context.support.StaticWebApplicationContext#onRefresh

Spring 事件监听器注册阶段

  • AbstractApplicationContext#registerListeners 方法
    • 将 ApplicationListener 添加到 AbstractApplicationContext#applicationEventMulticaster
    • 添加当前应用上下文所关联的 ApplicationListener 对象(集合)
    • 添加 BeanFactory 所注册 ApplicationListener Beans
    • 广播早期 Spring 事件
    • AbstractApplicationContext#earlyApplicationEvents

BeanFactory 初始化完成阶段

  • AbstractApplicationContext#finishBeanFactoryInitialization(ConfigurableListableBeanFactory) 方法

    • BeanFactory 关联 ConversionService Bean,如果存在

    • beanName 为 conversionServiceConversionService

    • 添加 StringValueResolver 对象

    • 如果 AbstractBeanFactory#embeddedValueResolvers 为空,添加一个

      if (!beanFactory.hasEmbeddedValueResolver()) {
        beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
      }
    
    • 依赖查找 LoadTimeWeaverAware Bean -- AOP

    • BeanFactory 临时 ClassLoader 置为 null

    • BeanFactory 冻结配置

    • DefaultListableBeanFactory#configurationFrozen

    • DefaultListableBeanFactory#frozenBeanDefinitionNames

    • BeanFactory 初始化非延迟单例 Beans

    1. 初始化非延迟单例 Bean
    2. 触发单例 Bean 中的 SmartInitializingSingleton 的生命周期, SmartInitializingSingleton#afterSingletonsInstantiated

    Spring 应用上下文刷新完成阶段

    • AbstractApplicationContext#finishRefresh 方法
    • 清除 ResourceLoader 缓存 - clearResourceCaches() @since 5.0
    • 初始化 LifecycleProcessor 对象 - initLifecycleProcessor()
    • 如果不存在 beanName 为 lifecycleProcessorLifecycleProcessor,则使用 DefaultLifecycleProcessor
    • 调用 LifecycleProcessor#onRefresh() 方法
    • 发布 Spring 应用上下文已刷新事件 - ContextRefreshedEvent
    • MBeanServer 托管 Live Beans

    Spring 应用上下文启动阶段

    • AbstractApplicationContext#start() 方法
    • 启动 LifecycleProcessor
    • 依赖查找 Lifecycle Beans
    • 启动 Lifecycle Beans
    • 发布Spring应用上下文已启动事件 - ContextStartedEvent

    Spring 应用上下文停止阶段

    • AbstractApplicationContext#stop() 方法
    • 停止 LifecycleProcessor
    • 依赖查找 Lifecycle Beans
    • 停止 Lifecycle Beans
    • 发布 Spring 应用上下文已停止事件 - ContextStoppedEvent

    Spring 应用上下文关闭阶段

    • AbstractApplicationContext#close() 方法
    • 状态标识:active(false)closed(true)
    • Live Beans JMX 撤销托管
    • LiveBeansView#unregisterApplicationContext(ConfigurableApplicationContext)
    • 发布 Spring 应用上下文已关闭事件 - ContextCLosedEvent
    • 关闭 LifecycleProcessor
    • 依赖查找 Lifecycle Beans
    • 停止 Lifecycle Beans
    • 销毁 Spring Beans
    • 关闭 BeanFactory
    • 回调 onClose()
    • 注册 Shutdown Hook 线程(如果曾注册)

    面试题

    Spring 应用上下文生命周期有哪些阶段?

    • 刷新阶段 - ConfigurableApplicationContext#refresh()
    • 启动阶段 - ConfigurableApplicationContext#start()
    • 停止阶段 - ConfigurableApplicationContext#stop()
    • 关闭阶段 - ConfigurableApplicationContext#close()

    Spring 应用上下文生命周期执行动作?

    课程加餐内容讨论

    为什么说 ObjectFactory 提供的是延迟依赖查找?

    • 原因
    • ObjectFactory (或 ObjectProvider )可关联某一类型 Bean
    • ObjectFactoryObjectProvider 对象在被依赖注入和依赖查询时并未实时查找关联类型的 Bean
    • ObjectFactory (或 ObjectProvider )调用 getObject() 方法时,目标 Bean 才被依赖查找
    • 总结
    • ObjectFactory (或 ObjectProvider )相当于某一类型 Bean 依赖查找代理对象

    依赖查找(注入)的Bean会被缓存吗?

    • 单例 Bean (Singleton) - 会
    • 缓存位置:org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#singletonObjects 属性
    • 原型 Bean (Prototype) - 不会
    • 当依赖查询或依赖注入时,根据 BeanDefinition 每次创建
    • 其他 Scope Bean
    • request : 每个 ServletRequest 内部缓存,生命周期维持在每次HTTP请求
    • session : 每个 HttpSession 内部缓存,生命周期维持在每个用户HTTP会话
    • application : 当前 Servlet 应用内部缓存

    @Bean 的处理流程是怎样的?

    • 解析范围 - Configuration Class 中的 @Bean 方法
    • 方法类型 - 静态 @Bean 方法和实例 @Bean 方法

    BeanFactory是如何处理循环依赖的?

    • 循环依赖开关(方法)- AbstractAutowireCapableBeanFactory#setAllowCircularReferences
    • 单例工程(属性)- DefaultSingletonBeanRegistry#singletonFactories
    • 获取早期未处理 Bean (方法)- AbstractAutowireCapableBeanFactory#getEarlyBeanReference
    • 早期未处理 Bean (属性)- DefaultSingletonBeanRegistry#earlySingletonObjects

    MyBatis 与 Spring Framework 是如何集成的?