【IoC】Spring IoC容器生命周期内容梳理

2023-11-15

Spring ApplicationContext Lifecycle

前言

关于Spring源码介绍的版本是:5.2.2.REALEASE,如果有流程不一致的地方,可以看下版本是否一致。

一、本文概览

Spring IoC容器生命周期整体看下来比较简单,但细节还是比较多的,其中最核心的方法就是AbstractApplicationContext#refresh了,除此方法外,还有AbstractApplicationContext#start、stop、close方法。下面是整个IoC容器生命周期的概览图,接下来我们依次去分析其中的细节项。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qjCAVk3o-1660488435509)(../img/SpringIoC容器生命周期.png)]

二、refresh-刷新阶段

刷新阶段是IoC生命周期中最为重要的一个阶段,里面包括上下文准备、容器创建、各种生命周期回调以及内建Bean创建等的操作,我们来看下其中的细节。

1、prepareRefresh()

容器刷新准备阶段,主要完成以下操作

  • 设置容器启动时间-startupDate
  • 容器关闭状态调整为false-closed(false)
  • 容器活跃状态调整为true-active(true)
  • 初始化PropertySources-initPropertySources()
    • 初始化上下文环境中的任何占位符属性源。
    • 默认空实现,由子类实现
  • 检查Environment中必须存在的属性
  • 初始化事件监听器集合
  • 初始化早期Spring事件集合

2、obtainFreshBeanFactory()

创建BeanFactory阶段,该方法细节内容由AbstractRefreshableApplicationContext#refreshBeanFactory实现

  • AbstractRefreshableApplicationContext#refreshBeanFactory

    • 如果当前上下文下有BeanFactory的话,就进行销毁Bean、关闭BeanFactory操作

    • 创建Spring框架内部唯一BeanFactory实现:DefaultListableBeanFactory

    • 设置BeanFactory ID,此ID用于反序列化操作

      • 自定义此BeanFactory,包括是否允许BeanDefinition覆盖操作、是否允许循环引用
        • Spring默认允许BeanDefinition覆盖操作,SpringBoot会自定义该实现,不允许BeanDefinition覆盖操作
        • Spring默认允许循环引用
    • 加载此BeanFactory下的所有BeanDefinition

    • 将此BeanFactory设置到当前Spring应用上下文中

  • getBeanFactory()

    • 返回Spring应用上下文底层BeanFactory

3、prepareBeanFactory(ConfiguableListableBeanFactory)

将BeanFactory应用于上下文前的BeanFactory准备阶段。

  • 关联当前上下文的ClassLoader
  • 设置Bean表达式处理器(SPEL)-StandardBeanExpressionResolver
  • 添加PropertyEditorRegistrar实现-ResourceEditorRegistrar
  • 添加Aware回调接口BeanPostProcessor实现-ApplicationContextAwareProcessor
    • 六大Aware接口回调,包括:EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware
  • 忽略Aware回调接口作为依赖注入接口
  • 注册ResolvableDependency对象-BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext
  • 添加ApplicationListenerDetector,该类的作用是为了检测内建实现ApplicationListener接口的Bean
  • 添加LoadTimeWeaverAwareProcessor,该类和AOP有关
  • 设置临时类加载器-ContextTypeMatchClassLoader
  • 注册单例Bean Environment、Map<String,Object> systemProperties以及OS环境变量

4、postProcessorBeanFactory(ConfigurableListableBeanFactory)

该方法为空实现,留给子类去重写。我们看到其子类实现都是WebApplicationContext,细节就不需要关注了,此方法的作用就是允许子类ApplicationContext实现中可以注册特殊的BeanPostProcessor
在这里插入图片描述

5、invokeBeanFactoryPostProcessor(ConfigurableListableBeanFactory)

BeanFactory后置处理阶段,这里面开始调用BeanFactoryPostProcessor或者BeanDefinitionRegistry的后置处理方法,处理顺序如下所示:

  • if beanFactory instanceof BeanDefinitionRegistry

    • 处理BeanDefinitionRegistry#postProcessBeanDefinitionRegistry(beanDefinitionRegistry)

      • 处理当前上下文的BeanFactoryPostProcessor中为BeanDefinitionRegistryPostProcessor的实例,调用其后置处理方法
      • 通过依赖查找注册在BeanFactory中并且实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor实例,随后将其进行排序后进行后置处理方法的调用
      • 通过依赖查找注册在BeanFactory中并且实现了Ordered接口的BeanDefinitionRegistryPostProcessor实例,随后将其进行排序并进行后置方法的调用
      • 通过依赖查找注册在BeanFactory中的普通BeanDefinitionRegistryPostProcessor实例,然后进行后置方法的调用
    • 处理BeanFactoryPostProcessor#postProcessBeanFactory

      • 先处理BeanDefinitionRegistryPostProcessor
        • 后处理普通的BeanFactoryPostProcessor
  • 处理剩余的BeanFactory中BeanFactoryPostProcessor

    • 也是按照优先级顺序来进行调用,首先要求没有在上面处理过,也就是在上面的if分支中处理过的。
    • 优先级按照 PriorityOrdered > Ordered > 普通

注册BeanPostProcessor以及临时类加载器,与AOP有关

6、registerBeanPostProcessor(ConfigurableListableBeanFactory)

  • 注册BeanPostProcessorChecker,此类的作用是当Bean创建是不符合所有的BeanPostProcessor条件时记录一条消息
  • 注册实现了PriorityOrdered接口的BeanPostProcessor,PriorityOrdered内部排序
  • 注册实现了Ordered接口的BeanPostProcessor,Ordered内部排序
  • 注册普通的BeanPostProcessor,无需排序
  • 注册Spring内建的BeanPostProcessor(MergedBeanDefinitionPostProcessor),按照优先级进行排序
  • 重新注册ApplicationListenerDetector(旧的删除,将其放至处理链的末尾)

7、initMessageSource()

初始化MessageSource,用于国际化

  • 如果BeanFactory中有MessageSource,则通过依赖查找获取MessageSource实例,如果该实例支持层次性并且当前上下文的MessageSource没有设置父类实例,就设置一下它的父类MessageSource实例
  • 如果BeanFactory中没有MessageSource实例,则初始化一个DelegatingMessageSource实例,并设置到当前上下文里,并且将当前实例注册到BeanFactory单例缓存中
    需要记住的是:每一个ApplicationContext都唯一对应一个MessageSource实例,但是实例内部是空内容。

8、initApplicationEventMulticaster()

初始化事件广播器,用于事件发布

  • 如果BeanFactory中有ApplicationEventMulticaster实例,则通过依赖查找获取ApplicationEventMulticaster实例,并且设置到当前上下文中
  • 如果BeanFactory中没有ApplicationEventMulticaster实例,则初始化一个SimpleApplicationEventMulticaster实例,用于事件广播,并且将该实例设置到当前上下文中以及注册到BeanFactory单例缓存中

9、onRefresh()

  • 此方法留给子类去扩展,用于特定上下文的特殊的bean初始化工作
    此方法都是有web相关的ApplicationContext来扩展的,包括以下部分:
    • AbstractRefreshableWebApplicationContext
    • EmbeddedWebApplicationContext
    • GenricWebApplicationContext
    • StaticWebApplicationContext

至于它们都初始化了什么特殊的bean先不关心,知道有这部分功能即可

10、registerListeners()

注册监听器

  • 首先注册上下文静态指定的监听器
  • 注册底层BeanFactory容器中注册的ApplicationListener
  • 发布早期事件(初始化事件广播之前发生的事件)

11、finishBeanFactoryInitialization(ConfigurableListableBeanFactory)

  • 初始化ConversionService类,用于类型转换,如果BeanFactory中有此对象,则通过依赖查找获取ConversionService对象并设置到beanFactory对应字段中,如果没有,则不操作。
  • 如果BeanFactory中没有EmbeddedValueResolvable,添加一个
  • 初始化LoadTimeWeaverAware Bean对象,首先去容器中查找LoadTimeWeaverAware相关类的名称,并依次通过依赖查找(通过bean名称),目的也是提前初始化
  • 将临时类加载器设置为null,停止使用临时类加载器(这个类加载器可能跟Spring AOP有关,提前去加载一些必要的类)
  • 冻结BeanDefinition注册行为,将DefaultListableBeanFactory中的beanDefinitionNames内容以数组的形式保存到frozenBeanDefinitionName字段中
  • 提前初始化容器中所有的剩下的单例Bean

12、finishRefresh()

上下文完成刷新阶段

  • 清除ResourceLoader缓存-clearResourceCaches
  • 初始化Lifecycle对象-initLifeCycleProcessor
  • 调用LifecycleProcessor#onRefresh方法
  • 发布容器已刷新事件
  • 向MBeanServer托管Live Bean

二、start-启动阶段

  • 启动LifecycleProcessor
    • 依赖查找Lifecycle Beans
    • 启动Lifecycle Bean
  • 发布容器已启动事件

三、close-关闭阶段

关闭此应用上下文,销毁BeanFactory中所有的Bean,销毁动作委托给doClose()方法

  • closed(true)
  • Live Beans JMX撤销托管
  • 发布容器关闭事件
  • 关闭LifecycleProcessor
    • 依赖查找所有的Lifecycle Beans
    • 停止 Lifecycle Beans
  • 销毁Spring Beans
  • 关闭BeanFactory
  • 回调onClose()-子类实现
  • 清除早期的事件监听器
  • active(false)
  • 删除Shutdown Hook,如果我们注册过的话

四、stop-停止阶段

  • 停止LifecycleProcessor
    • 依赖查找Lifecycle Beans
    • 停止Lifecycle Bean
  • 发布容器已停止事件

五、总结

对于Spring IoC容器的生命周期大致就是上述总结的流程,它包括刷新、启动、停止、关闭阶段,其中最为重要的就是刷新阶段了,其他是需要我们去手动调用才能生效的方法。对于这些阶段其中的某些细节,我目前也不是很清楚,接下来便继续开展其细节的学习记录,例如Bean生命周期、国际化、资源管理、类型转换等内容。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【IoC】Spring IoC容器生命周期内容梳理 的相关文章

随机推荐

  • 全网最全C盘清理指南,无需安装清理软件,值得收藏

    最近电脑运行卡顿 打开一看 原来C盘爆红了 找了一个b站的清理教程 此篇来做一个总结 会讲哪些能删哪些不能删 以及原因 无需安装如360 腾讯电脑管家之类的清理软件 原视频链接 up主 小宇Boihttps www bilibili com
  • 决策树模型

    决策树模型是机器学习的各种算法模型中比较好理解的一种模型 它的基本原理是通过对一系列问题进行if else的推导 最终实现相关决策 下图所示为一个典型的决策树模型 员工离职预测模型的简单演示 该决策树首先判断员工满意度是否小于5 若答案为
  • TCL命令

    目录 list命令 concat命令 lindex命令 llength命令 linsert命令 lreplace命令 lrange命令 lappend命令 lsearch命令 lsort命令 split命令 join命令 list命令 li
  • JSP webshell免杀——JSP的基础

    唉 每次开启JSP都要好一会儿 话说我也不知道为啥 我的每次开启条件一次比一次苛刻 一开始必应就可以打开 再后来只能由谷歌打开 现在可好了得开着代理用谷歌才能进去 一个JSP页面可由5种元素组合而成 1 普通的HTML标记和JavaScri
  • 梳理半月有余,精心准备了17张知识思维导图,这次要讲清统计学

    想要学好数据分析 统计学是必学的基础课程 统计学看似简单 实则知识多而繁杂 对于初学小白来说更是不知所措 理不清知识架构体系 为了让大家对统计学有更加清晰地认识 我总结了17 张 统计学知识思维导图 今天分享给大家 图片上传后会自动压缩 如
  • Nuxt3打包部署到Linux(node+pm2详细安装运行步骤)

    小聊 最近写了一个项目 需要打包部署 过程还是比较繁琐的 因为需要先配置运行环境 准备采用 pm2 管理项目运行 需要在服务器安装 pm2 而安装 pm2 的话用 npm 命令最方便 所以还要下载 node 环境 那么 就让我们一步步的完成
  • Nmap扫描原理与用法

    Nmap扫描原理与用法 2012年6月16日 1 Nmap介绍 Nmap扫描原理与用法PDF 下载地址 Nmap是一款开源免费的网络发现 Network Discovery 和安全审计 Security Auditing 工具 软件名字Nm
  • ‘mvn‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件——解决方法(详解,亲测有效)

    错误原因 配置Maven环境变量出现问题 解决方法 以windows 10为例子 步骤一 此电脑 属性 高级系统设置 环境变量 系统变量 新建 变量名 M2 HOME 变量值 D install maven apache maven 3 5
  • jq和vue的区别

    1 从jquery到vue的转变是一个思想想的转变 就是将原有的直接操作dom的思想转变到操作数据上去 2 传统前端开发模式中是以jq为核心的 而vue是现在一个兴起的前端js库 是一个精简的MVVM 3 jQuery是使用选择器 选取DO
  • spring boot定时任务方式

    一 定时任务实现的几种方式 Timer jdk util自带的Timer类 可以调度一个java util TimerTask任务 只能设定任务按照某个频度执行 但不能按设定时间运行 ScheduledExecutorService jdk
  • 使用Python进行测试驱动开发

    作者 Jason Diamond 译者 吴海燕 原文发表日期 12 02 2004 翻译日期 2 17 2005 原文件位置 http www onlamp com pub a python 2004 12 02 tdd pyunit ht
  • 微信小程序使用npm引入三方包详解

    目录 1 前言 2 微信小程序npm环境搭建 2 1 创建package json文件 2 2 修改 project config json 2 3 修改project private config json配置 2 4 构建 npm 包
  • sharepoint 2010 列表数据分页控件介绍 pagination UserControl

    这里主要是介绍下最近开发的一个sharepoint列表或者文档库的分页控件 并且把它包装成一个可以支持自定义列表 Custom list 文档库 Document library 讨论板 Discussion 资源库 Assets libr
  • 创建vue项目-vue2&vue3

    1 安装node 网址 下载 Node js 中文网 可以下载最新版本 也可以点击下方按钮下载其他版本 安装时全部选择默认 点击下一步 完成之后打开cmd命令窗口 检查node js是否安装成功 再查看npm是否安装成功 2 安装vue脚手
  • Redis-事务与持久化

    目录 事务 事务命令 事务的实现 事务的开始 命令入队 事务队列 执行事务 WATCH命令 不监视的情况下 监视的情况下 事务的ACID特性 A 原子性 C 一致性 I 隔离性 D 持久性 持久化 RDB持久化 Redis DataBase
  • 搜狐畅游2018年9月15日校招真题(2)

    通过该道题目 题目描述 示例代码 include
  • 苹果的「AI 建筑师」GAUDI:根据文本生成 3D 场景

    作者 李梅 编辑 陈彩娴 转载自 AI科技评论 aitechtalk 如今 每隔一段时间就有新的文本生成图像模型释出 个个效果都很强大 每每惊艳众人 这个领域已经是卷上天了 不过 像 OpenAI 的 DALL E 2 或谷歌 的 Imag
  • devops之gcp core infrastructure fundamental,应用云;开发、部署、监控

    最后更新2022 02 09 应用云 下面来看看GCP提供什么应用PaaS服务 app engine是提供标准API的 预安装 application 自动部署 自动扩展 经济 免费每日额度 基于使用的计费 SDK 满足开发 测试 部署要求
  • 微信小程序是如何上传文件以及下载文件

    微信小程序可以使用wx uploadFile API来上传文件 使用wx downloadFile API来下载文件 上传文件的步骤如下 1 创建一个选择文件的按钮 2 用户点击按钮后 调用wx chooseImage 方法来选择文件 3
  • 【IoC】Spring IoC容器生命周期内容梳理

    Spring ApplicationContext Lifecycle 前言 关于Spring源码介绍的版本是 5 2 2 REALEASE 如果有流程不一致的地方 可以看下版本是否一致 一 本文概览 Spring IoC容器生命周期整体看