什么是refresh?Spring refresh 流程
refresh 是 AbstractApplicationContext 中的一个方法,负责初始化 ApplicationContext 容器,容器必须调用 refresh 才能正常工作。它的内部主要会调用 12 个方法,我们把它们称为 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
功能分类
1 为准备环境
2 3 4 5 6 为准备 BeanFactory
7 8 9 10 12 为准备 ApplicationContext
11 为初始化 BeanFactory 中非延迟单例 bean
具体步骤
1. prepareRefresh
* 这一步创建和准备了 Environment 对象,它作为 ApplicationContext 的一个成员变量
* Environment 对象的作用之一是为后续 @Value,值注入时提供键值
* Environment 分成三个主要部分
* systemProperties - 保存 java 环境键值
* systemEnvironment - 保存系统环境键值
* 自定义 PropertySource - 保存自定义键值,例如来自于 *.properties 文件的键值

2. obtainFreshBeanFactory
* 这一步获取(或创建) BeanFactory,它也是作为 ApplicationContext 的一个成员变量
* BeanFactory 的作用是负责 bean 的创建、依赖注入和初始化,bean 的各项特征由 BeanDefinition 定义
* BeanDefinition 作为 bean 的设计蓝图,规定了 bean 的特征,如单例多例、依赖关系、初始销毁方法等
* BeanDefinition 的来源有多种多样,可以是通过 xml 获得、配置类获得、组件扫描获得,也可以是编程添加
* 所有的 BeanDefinition 会存入 BeanFactory 中的 beanDefinitionMap 集合

3. prepareBeanFactory
* 这一步会进一步完善 BeanFactory,为它的各项成员变量赋值
* beanExpressionResolver 用来解析 SpEL,常见实现为 StandardBeanExpressionResolver
* propertyEditorRegistrars 会注册类型转换器
* 它在这里使用了 ResourceEditorRegistrar 实现类
* 并应用 ApplicationContext 提供的 Environment 完成 ${ } 解析
* registerResolvableDependency 来注册 beanFactory 以及 ApplicationContext,让它们也能用于依赖注入
* beanPostProcessors 是 bean 后处理器集合,会工作在 bean 的生命周期各个阶段,此处会添加两个:
* ApplicationContextAwareProcessor 用来解析 Aware 接口
* ApplicationListenerDetector 用来识别容器中 ApplicationListener 类型的 bean

4. postProcessBeanFactory
* 这一步是空实现,留给子类扩展。
* 一般 Web 环境的 ApplicationContext 都要利用它注册新的 Scope,完善 Web 下的 BeanFactory
* 这里体现的是模板方法设计模式
5. invokeBeanFactoryPost Processors
* 这一步会调用 beanFactory 后处理器
* beanFactory 后处理器,充当 beanFactory 的扩展点,可以用来补充或修改 BeanDefinition
* 常见的 beanFactory 后处理器有
* ConfigurationClassPostProcessor – 解析 @Configuration、@Bean、@Import、@PropertySource 等
* PropertySourcesPlaceHolderConfigurer – 替换 BeanDefinition 中的 ${ }
* MapperScannerConfigurer – 补充 Mapper 接口对应的 BeanDefinition

6. registerBeanPost Processors
* 这一步是继续从 beanFactory 中找出 bean 后处理器,添加至 beanPostProcessors 集合中
* bean 后处理器,充当 bean 的扩展点,可以工作在 bean 的实例化、依赖注入、初始化阶段,常见的有:
* AutowiredAnnotationBeanPostProcessor 功能有:解析 @Autowired,@Value 注解
* CommonAnnotationBeanPostProcessor 功能有:解析 @Resource,@PostConstruct,@PreDestroy
* AnnotationAwareAspectJAutoProxyCreator 功能有:为符合切点的目标 bean 自动创建代理

7. initMessageSource
* 这一步是为 ApplicationContext 添加 messageSource 成员,实现国际化功能
* 去 beanFactory 内找名为 messageSource 的 bean,如果没有,则提供空的 MessageSource 实现

8. initApplication ContextEventMulticaster
* 这一步为 ApplicationContext 添加事件广播器成员,即 applicationContextEventMulticaster
* 它的作用是发布事件给监听器
* 去 beanFactory 找名为 applicationEventMulticaster 的 bean 作为事件广播器,若没有,会创建默认的事件广播器
* 之后就可以调用 ApplicationContext.publishEvent(事件对象) 来发布事件

9. onRefresh
* 这一步是空实现,留给子类扩展
* SpringBoot 中的子类在这里准备了 WebServer,即内嵌 web 容器
* 体现的是模板方法设计模式
10. registerListeners
* 这一步会从多种途径找到事件监听器,并添加至 applicationEventMulticaster
* 事件监听器顾名思义,用来接收事件广播器发布的事件,有如下来源
* 事先编程添加的
* 来自容器中的 bean
* 来自于 @EventListener 的解析
* 要实现事件监听器,只需要实现 ApplicationListener 接口,重写其中 onApplicationEvent(E e) 方法即可

11. finishBeanFactory Initialization
* 这一步会将 beanFactory 的成员补充完毕,并初始化所有非延迟单例 bean
* conversionService 也是一套转换机制,作为对 PropertyEditor 的补充
* embeddedValueResolvers 即内嵌值解析器,用来解析 @Value 中的 ${ },借用的是 Environment 的功能
* singletonObjects 即单例池,缓存所有单例对象
* 对象的创建都分三个阶段,每一阶段都有不同的 bean 后处理器参与进来,扩展功能

12. finishRefresh
* 这一步会为 ApplicationContext 添加 lifecycleProcessor 成员,用来控制容器内需要生命周期管理的 bean
* 如果容器中有名称为 lifecycleProcessor 的 bean 就用它,否则创建默认的生命周期管理器
* 准备好生命周期管理器,就可以实现
* 调用 context 的 start,即可触发所有实现 LifeCycle 接口 bean 的 start
* 调用 context 的 stop,即可触发所有实现 LifeCycle 接口 bean 的 stop
* 发布 ContextRefreshed 事件,整个 refresh 执行完成

相关文章:
什么是refresh?Spring refresh 流程
refresh 是 AbstractApplicationContext 中的一个方法,负责初始化 ApplicationContext 容器,容器必须调用 refresh 才能正常工作。它的内部主要会调用 12 个方法,我们把它们称为 refresh 的 12 个步骤:1. prepareRefresh2. obtain…...
Python登陆系统
前言 #源码见文末公众号哈# 登录系统 一个简单的登录系统包含了登录账户、注册账户、修改密码以及注销账户的操作。 1. 登录账户 登录系统主要需要判断账户是否存在,不存在就注册一个账户,如果第一次登录系统,我们需要先新建一个文件&…...
【新2023】华为OD机试 - 重组字符串(Python)
华为 OD 清单查看地址:blog.csdn.net/hihell/category_12199275.html 重组字符串 题目 给定一个非空字符串 S,其被 N 个‘-’分隔成 N+1 的子串,给定正整数 K, 要求除第一个子串外,其余的子串每 K 个字符组成新的子串,并用‘-’分隔。 对于新组成的每一个子串,如果它…...
视频监控流程图
<html> <head> <meta http-equiv"Content-Type" content"text/html; charsetUTF-8"/> <link rel"stylesheet" type"text/css" href"visio.css"/> <title> 视频监控流程图 </title> <…...
普通单双面板的生产工艺流程之图形转移,华秋一文告诉你
衔接上文,继续为朋友们分享普通单双面板的生产工艺流程。 如图,第五道主流程为图形转移。 图形转移的目的为: 利用光化学原理,将图形线路的形状转移到印制板上,再利用化学原理,将图形线路在印制板上制作出…...
1.8 providers
生成providersnest g service <name>providers的注入方式构造函数注入Injectable() export class KeywordService {constructor(private readonly httpService: HttpService,private readonly pro: ProService,) {} }Inject()注入export class KeywordController {Inject…...
如何编写一个基本的 Verilog Module(模块)
1、概述这篇文章主要介绍了 Verilog 在 FPGA 设计中的概念和使用方法。首先讨论使用模块(module)关键字构造 Verilog 设计的方式,以及这与所描述的硬件的关系。这包括对参数、端口(port)和例化(instantiato…...
让乔布斯想要「发动核战争」的 Android,为何成了占有率最高的系统?
2008 年 9 月 23 日,Apple 的创始人和 CEO 史蒂夫乔布斯像往常一样走进了公司,此时距离初代 iPhone 的发布会才过了一年半,这款充满了争议的产品就像一块从山崖滚落的巨岩,一路电光石火的给手机市场的《小石潭记》来了场焚书坑儒。…...
FPGA开发软件(vivado + modelsim)环境搭建(附详细安装步骤+软件下载)
本文详细介绍了vivado软件和modelsim软件的安装,以及vivado中配置modelsim仿真设置,每一步都加文字说明和图片。一、软件安装包下载1、vivado vivado版本很多,目前最新的已更新到vivado2022.2,版本越高,安装包越大&…...
TypeScript 学习之类型
布尔类型 类型: boolean最简单的类型,值只有 true/false let isDone: boolean true;数字类型 类型:number数字都是浮点数,支持二进制、八进制、十进制、十六进制。 let decLiteral: number 16; // 十进制 let hexLiteral: number 0xf0…...
基于MATLAB计算MIMO信道容量(附完整代码与分析)
目录 一.介绍 二. 代码 三. 运行结果及分析 3.1 MIMO信道容量:固定发射天线数为4 3.2 MIMO信道容量:固定接收天线数为4 3.3 AWGN信道与瑞利信道容量 四. 总结 一.介绍 本文章将在MATLAB环境中分析MIMO信道容量,AWGN信道容量…...
CSDN城市开发者联盟、C友会期待你的加入
文章目录🌟 课前小差🌟 chatGPT🌟 CSDN中的持续学习🌟 23年原力计划🌟 C友会、CDC🌟 如何关联本地的开发者?🌟 写在最后🌟 课前小差 哈喽,大家好,…...
【新2023】华为OD机试 - 吃火锅(Python)
华为 OD 清单查看地址:blog.csdn.net/hihell/category_12199275.html 吃火锅 题目 入职后,导师会请你吃饭,你选择了火锅, 火锅里会在不同时间下很多菜, 不同食材要煮不同时间,才能变得刚好合适, 你希望吃到最多的刚好合适的菜, 但是你的手速不够快用m代替手速, 每次…...
类似LeetCode的登录页面(小程序版)
前言每一个项目都会有用户端的注册和登录页面,对于刚入门的小白来说,在UI设计方面不太擅长,就算大致的UI界面设计出来了,但是落实到代码上来实现的时候就很容易卡住。这篇博客主要介绍的就是仿作一个类似LeetCode登录的简约大方页…...
CUDA的统一内存
CUDA的统一内存 文章目录CUDA的统一内存N.1. Unified Memory IntroductionN.1.1. System RequirementsN.1.2. Simplifying GPU ProgrammingN.1.3. Data Migration and CoherencyN.1.4. GPU Memory OversubscriptionN.1.5. Multi-GPUN.1.6. System AllocatorN.1.7. Hardware Coh…...
MySQL-其他函数(补充)
格式化函数FORMAT(x, n) 例:将数字x进行格式化,以四舍五入的方式保留n位小数,结果以字符串的形式返回mysql> select format(12.3456,3),format(2.2,4),format(9.333,0); --------------------------------------------------- | format(12…...
MySQL Study Notes Design in 2023
文章目录1 概述1.1 MySQL相关概述1.2 数据模型1.3 SQL分类2 数据库设计-DDL2.1 约束2.2 字段3 数据库操作-DML3.1 增加(insert)1 概述 1.1 MySQL相关概述 数据库:英文为 DataBase,简称DB,它是存储和管理数据的仓库。 数据库管理系统…...
C++ 修改防火墙firewall设置(Windows)
文章目录1、简介1.1 防火墙概述1.2 入站,还是出站?1.3 防火墙规则优先级2、系统界面方式3、命令行方式3.1 防火墙基本状态设置3.2 入站出站规则设置3.3 其他设置3.4 telnet检测端口4、C方式4.1 注册表4.2 COM(Windows XP)4.3 COM&…...
Spring 入门教程详解
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...
day43【代码随想录】动态规划之一和零、完全背包理论基础
文章目录前言一、一和零(力扣474)二、完全背包前言 1、一和零 2、完全背包理论基础 一、一和零(力扣474) 求装满这个背包最多有多少个物品 给你一个二进制字符串数组 strs 和两个整数 m 和 n 。 请你找出并返回 strs 的最大子集…...
2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面
代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http…...
新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
随着新能源汽车的快速普及,充电桩作为核心配套设施,其安全性与可靠性备受关注。然而,在高温、高负荷运行环境下,充电桩的散热问题与消防安全隐患日益凸显,成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...
企业如何增强终端安全?
在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...
Golang——6、指针和结构体
指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...
FFmpeg:Windows系统小白安装及其使用
一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】,注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录(即exe所在文件夹)加入系统变量…...
Golang——7、包与接口详解
包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...
适应性Java用于现代 API:REST、GraphQL 和事件驱动
在快速发展的软件开发领域,REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名,不断适应这些现代范式的需求。随着不断发展的生态系统,Java 在现代 API 方…...
ubuntu22.04 安装docker 和docker-compose
首先你要确保没有docker环境或者使用命令删掉docker sudo apt-get remove docker docker-engine docker.io containerd runc安装docker 更新软件环境 sudo apt update sudo apt upgrade下载docker依赖和GPG 密钥 # 依赖 apt-get install ca-certificates curl gnupg lsb-rel…...
