Spring之refresh的12个步骤

2023-11-14

     根据B站黑马视频总结

1. refresh的12个步骤

  1. prepareRefresh
  2. obtainFreshBeanFactory
  3. prepareBeanFactory
  4. postProcessBeanFactory
  5. invokeBeanFactoryPostProcessors
  6. registerBeanPostProcessors
  7. initMessageSource
  8. initApplicationEventMulticaster
  9. onRefresh
  10. registerListeners
  11. finishBeanFactoryInitialization
  12. finishRefresh
  • 步骤2-6是创建并准备beanFactory对象
  • 步骤7-12是完善applicationContext的其他功能
    • 步骤11是创建非懒加载的单例对象

1.1 prepareRefresh

  • 准备上下文环境
  • 创建了一个Environment对象
    • systemProperties:保存Java环境变量的键值
    • systemEnvironment:保存了系统环境变量的键值
    • 自定义properSource:保存了配置文件中的键值

1.2 obtainFreshBeanFactory

  • 创建BeanFactory,它也是作为ApplicationContext的一个成员变量(其实ApplicationContext也继承了BeanFactory)
  • 为beanFactory中的成员变量beanDefinitionMap(是个容器)进行初始化,该map的作用是保存BeanDefinition对象
    • BeanDefinition作为bean的设计蓝图,规定了bean的特征,如单例、依赖关系、初始销毁方法

1.3 prepareBeanFactory

  • 进一步完善beanFactory。为它的其他各项成员变量赋值
  • beanExpressionResolver:用来解析SpEL。
  • propertyEditorRegisters:类型转换器
    • 它在这里使用了ResourceEditorRegister实现类
    • 并应用ApplicationContext提供的Environment完成${}解析
  • registerResolvableDependency:是个容器,用于管理一些特殊的bean。如注册beanFactory以及ApplicationContext。让这些对象也能用于依赖注入。
  • beanPostProcessors:是个容器,用于管理bean后置处理器,bean的后置处理器会在bean的生命周期的各个阶段进行工作。此处会自动给我们添加两个bean后置处理器
    • ApplicationContextAwareProcessor:用来解析Aware接口
    • ApplicationListenerDetector:用于识别容器中ApplicationListener类型的bean
  • 单例池中也会添加一些基本的单实例bean(environment,systemProperties等)

1.4 postProcessBeanFactory 

  • 是一个空实现,留给子类扩展。这里体现了模板方法设计模式
  • 如在web环境的ApplicationContext重写该方法来实现注册新的Scope,完善web下的BeanFactory

1.5 invokeBeanFactoryPostProcessors

  • 这一步会调用所有的beanFactory后置处理器。
  • beanfactory后置处理器作用是充当beanFactory的扩展点,可以添加或修改BeanDefinition
  • 我们可以自定义beanFactory后置处理器,只要实现BeanFactoryPostProcessor接口即可。当容器刷新执行到这个步骤会自动调用我们实现的接口方法。
  • 常见的beanFactory后置处理器有
    • ConfigurationClassPostProcessor:解析@Configuration,@Bean,@Import,@PropertySource,并向beanDefinitionMap中添加相应的beanDefinition对象(补充:这个需要优先执行,而且还是系统自动帮我们创建的。因为其他beanFactory后置处理器比如我们自定义的beanFactory后置处理器是需要先解析生成对应的BeanDefinition对象信息,然后才能生成bean对象(如果需要还会将这个bean放入单例池中)执行,而生成对应的beanDefinition对象信息就需要借助ConfigurationClassPostProcessor来实现)
    • MapperScannerConfigurer:向beanDefinitionMap中添加Mapper接口对应的BeanDefinition对象。

1.6  registerBeanPostProcessors

  • 继续从beanDefinitionMap中找出所有的bean后置处理器,生成实例对象并保存到beanPostProcessors集合中
  • beanPostProcessor:bean的后置处理器,充当bean的扩展点,它们会工作在bean的实例化、依赖注入、初始化阶段前后。常见的bean后置处理器有
    • AutowiredAnnotationBeanPostProcessor:解析@Autowired,@Value注解
    • CommonAnnotationBeanPostProcessor:解析 @Resource,@PostConstruct,@PreDestroy
    • AnnotationAwareAspectJAutoProxyCreator:为符合切点的目标bean自动创建代理

1.7 initMessageSource

  • 向ApplicationContext添加messageSource成员,实现国际化功能
  • 在beanDefinitionMap中找名为messageSource的bean定义信息,如果没有,则提供一个空的MessageSource实现(会将这个空实现bean放入单例池中

1.8 initApplicationContextEventMulticaster 

  • 向ApplicationContext的成员变量applicationEventMulticaster赋值(初始化)
  • applicationEventMulticaster是一个事件广播器,它里面维护了一个集合,该集合保存了spring容器的所有监听器。
    • 如果需用用事件广播器发生事件,则事件广播器就会遍历它所维护的集合,然后给相应的监听器发送事件。
  • 查找beanDefinitionMap中是否有名为applicationEventMulticaster的beanDefinition信息,若没有,则会创建一个默认的事件广播器(也会将这个bean放入单例池中),用来发布事件。

1.9  onRefresh

  • 这一步也是一个空实现,留给子类扩展。模板方法模式
  • 如springboot中的子类在这里准备了WebServer(内嵌web容器)

1.10 registerListeners

  • 从多种途径中找到事件监听器对象,并添加到applicationEventMulticaster维护的集合当中
  • 事件监听器对象的来源
    • 实现编程添加的
    • 来自容器的bean(通过实现ApplicationListener接口,当然如果需要也会将这个bean放入单例池中)
    • 来自@EventListener注解的解析(容器帮我们生成一个事件监听器对象)

1.11 finishBeanFactoryInitialization

  • 这一步会将beanFactory的成员补充完毕。并且初始化剩下的所有的非懒加载单例bean
  • conversionService:也是一套类型转换机制,是对propertyEditorRegistrars的补充。
  • embeddedValueResolvers:内嵌值解析器。其实是对Environment的封装,用来解析@Value中的${}
  • singletonObjects:继续向单例池中添加剩余的非懒加载的单例bean。重点
    • 添加的过程中,beanPostProcessors中的bean后置处理器也会工作

1.12  finishRefresh

  • 这一步会为ApplicationContext添加lifecycleProcessor成员。用来控制容器内需要生命周期管理的bean
  • 去容器的单例池中寻找有没有名为lifecycleProcessor的bean就用它,如果没有则默认创建一个生命周期管理器(是spring容器的生命周期,也会加入单例池)
  • 生命周期管理的意思:
    • 当调用spring容器context的start方法。则触发所有实现LifeCycle接口bean的start方法
    • 当调用spring容器context的stop方法。则触发所有实现LifeCycle接口bean的stop方法。
  • 发布一个ContextRefreshed事件,表示整个refresh完成执行完成。

 2. 总结

  1. prepareRefresh:准备好环境变量,配置变量
  2. obtainFreshBeanFactory:创建或获取bean工厂
  3. prepareBeanFactory:准备bean工厂
  4. postProcessBeanFactory:子类去扩展bean工厂
  5. invokeBeanFactoryPostProcessors:自定义beanFactory后置处理器去扩展bean工厂
  6. registerBeanPostProcessors:准备bean后置处理器
  7. initMessageSource:为spring容器提供国际化功能
  8. initApplicationEventMulticaster:为spring容器提供事件发布器
  9. onRefresh:留给子类对spring容器进行扩展
  10. registerListeners:为spring容器注册监听器
  11. finishBeanFactoryInitialization:初始化剩余的非懒加载单例bean,执行bean后置处理器扩展
  12. finishRefresh:准备spring容器生命周期管理器,发布contextRefreshed事件

 

 

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

Spring之refresh的12个步骤 的相关文章

随机推荐

  • 普通函数与模板函数的调用规则

    普通函数与模板函数的调用规则 1 如果函数模板和普通函数都可以实现 优先调用普通函数 2 可以通过空模板参数列表来强制调用函数模板 3 函数模板也可以发生重载 4 如果函数模板可以产生更好的匹配 优先调用函数模板 代码示例 1 如果函数模板
  • JS中sort方法排序

    JS中sort方法排序 一 数字排序 string类型 二 数字排序 string类型和number类型 三 混合排序 string number和字母 四 函数排序 五 数组对象排序 一 数字排序 string类型 var arr 1 2
  • 【翻译】如何选择一个开源软件许可证 Choosing an OSS license doesn’t need to be scary...

    本文禁止转载 选择一个开源软件许可证并不需要很可怕 下列哪一项最能描述你的情况 我想简单和宽容 MIT许可证是一个许可证 就是短了点 它让人们做任何他们想与你的代码 只要他们提供归属回你和不承担你的责任 jQuery和Rails使用MIT许
  • Mysql5.7_SpatialAnalysisFunctions空间分析函数

    Mysql5 7 SpatialAnalysisFunctions空间分析函数 12 17 Spatial Analysis Functions 空间分析函数 12 17 1 Spatial Function Reference空间函数参考
  • Springboot项目启动后无法打开jsp、html等页面问题(@RestController与@ResponseBody + @Controller的区别)

    今天试着用IDEA构建一个springboot mybatis druid整合的项目 刚配置完 想测试一下启动项目 然后通过controller层打开一个html页面 结果发现一直打不开 代码和配置都是对的 最后发现掉屎坑里去了 一开始在c
  • 群G及群运算

    定义 一个 非空集合G中 如果定义了 一个 乘法 运算 元素的二元运算 满足以下四个性质 那么该非空集合G称为群 封闭性 a b G a b c G 结合律 a b c G a b c a b c 单位元 e G a G e a a e a
  • hadoop初级到资深

    hadoop初级到资深 2015 06 13 12 08 165人阅读 评论 0 收藏 举报 分类 hadoop 3 1 hadoop是什么 适合大数据的分布式存储与计算平台 2 hadoop版本有哪些 Apache 官方版本 1 1 2
  • 数据库表结构设计方法及原则

    在目前的企业信息系统中 数据库还是最佳的数据存储方式 虽然已经有很多的书籍在指导我们进行数据库设计 但应该那种方式是设计数据库的表结构的最好方法 设计时应遵从什么样的原则 四个范式如何能够用一种方式达到顺畅的应用等是我一直在思考和总结的问题
  • 计算机组成原理(海明码效验)(3)-软件设计(二十四)

    计算机组成原理 2 软件设计 二十三 https blog csdn net ke1ying article details 129394115 一 总线 分为 内部总线 系统总线 外部总线 内部总线 指芯片级别的总线 连接各个芯片 系统总
  • 广义线性模型——Logistic回归模型(1)

    广义线性模型 GLM 是线性模型的扩展 它通过连接函数建立响应变量的数学期望值与线性组合的预测变量之间的关系 广义线性模型拟合的形式为 其中g Y 是条件均值的函数 称为连接函数 另外 你可放松Y为正态分布的假设 改为Y 服从指数分布族中的
  • 12-git-pycharm配置.ignore文件

    pycharm配置 ignore文件 前言 安装插件 使用 添加其他忽略文件 前言 在开发中经常需要配置提交git的忽略文件 本篇来学习下使用pycharm自动生成 ignore文件 安装插件 Files gt setting gt Plu
  • 基于区块链技术的电子病历研究----2019年5月份

    FJTCM区块链技术开发学习小组 时间 2019 05 31 基于区块链技术的电子病历研究 摘 要 提出了一种基于区块链技术的新型分布式电子病历记录管理系统 系统为患者提供了一个全面的 不可变的日志 并且可以方便地访问其医疗信息 利用独特的
  • JQuery隐藏、添加select的option

    需求 级联查询 根据前一个select选择的值 动态改变后一个select的值 页面效果大致如下 代码 ul li p 设备类型 p li ul
  • MySQL 数据库

    MySQL 数据库 概念 数据 所谓数据 Data 是指对客观事物进行描述并可以鉴别的符号 这些符号是可识别的 抽象的 它不仅仅指狭义上的数字 而是有多种表现形式 字母 文字 文本 图形 音频 视频等 现在计算机存储和处理的数据范围十分广泛
  • Vue 3.0双向绑定原理的实现

    proxy方法 vue js 是采用数据劫持结合发布者 订阅者模式的方式 通过new Proxy 来劫持各个属性的setter getter 在数据变动时发布消息给订阅者 触发相应的监听回调 Vue 3 0与Vue 2 0的区别仅是数据劫持
  • Python while循环语句语法格式

    视频版教程 Python3零基础7天入门实战视频教程 初始化语句 while 循环条件 循环体 迭代语句 初始化语句 一条或多条语句 用于完成一些初始化工作 初始化语句在循环开始之前执行 循环条件 这是一个布尔表达式 这个表达式能决定是否执
  • 主板电源接口示意图_台式电脑主板的接口线及安装细节图解

    如果你是玩台式电脑用户 那么你肯定知道 电脑最麻烦的就是主板上的接口了 稍有不慎接错线主板就会烧毁 因此这是一个很重要的环节 今天小编就来给大家介绍主板上的接口都是些什么 该怎么接 01 认识主板供电接口 在主板上 我们可以看到一个长方形的
  • 实证论文|数据处理问题合集

    目录 1stata 如何留下至少有连续5年的观测 2stata如何剔除13年及以后公司样本 python 3stata如何根据文本数据生成新数据 4如何将季度数据处理为年度数据 5如何根据分位数划分组别 6如何将省份划分为东中西部地区 7出
  • Java-1.9

    题目描述 编写程序 显示宽为4 5 高为7 9的矩形的面积和周长 代码 public class Rectangle public static void main String args final double width 4 5 he
  • Spring之refresh的12个步骤

    根据B站黑马视频总结 1 refresh的12个步骤 prepareRefresh obtainFreshBeanFactory prepareBeanFactory postProcessBeanFactory invokeBeanFac