【Spring Boot刷新上下文核心流程详解】

Spring Boot 刷新上下文核心流程详解

一、前言

在使用 Spring Boot 启动应用时,控制台会打印出一大串日志,其中最核心的启动动作之一就是 刷新上下文(refresh)。
refresh 方法不仅负责 Bean 的创建与初始化,还涉及监听器、国际化、多环境配置等多个模块,是 Spring Boot 启动的核心环节。
本文将结合源码,带你从入口到细节剖析刷新上下文的全过程。

二、入口位置

实例方法SpringApplication#run
在这里插入图片描述
好,那我帮你写一篇**《Spring Boot 刷新上下文核心流程详解》**的 CSDN 博客文章,结构会清晰、逻辑循序渐进,既有源码分析又有配图思路,读者看完能对整个 refresh 流程有一个比较完整的理解。


Spring Boot 刷新上下文核心流程详解

一、前言

在使用 Spring Boot 启动应用时,控制台会打印出一大串日志,其中最核心的启动动作之一就是 刷新上下文(refresh)
refresh 方法不仅负责 Bean 的创建与初始化,还涉及监听器、国际化、多环境配置等多个模块,是 Spring Boot 启动的核心环节。
本文将结合源码,带你从入口到细节剖析刷新上下文的全过程。


二、入口位置

Spring Boot 的启动入口通常是:

SpringApplication.run(Application.class, args);

调用链简化如下:

SpringApplication.run()-> SpringApplication.refreshContext()-> AbstractApplicationContext.refresh()

核心就在 AbstractApplicationContext.refresh() 方法中,这也是所有 Spring 上下文实现(如 AnnotationConfigServletWebServerApplicationContext)的基础模板方法。


三、源码流程概览

AbstractApplicationContext# refresh() 的主要执行步骤如下(简化版):

public void refresh() throws BeansException, IllegalStateException {this.startupShutdownLock.lock();try {this.startupShutdownThread = Thread.currentThread();StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");this.prepareRefresh();ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();this.prepareBeanFactory(beanFactory);try {this.postProcessBeanFactory(beanFactory);StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");this.invokeBeanFactoryPostProcessors(beanFactory);this.registerBeanPostProcessors(beanFactory);beanPostProcess.end();this.initMessageSource();this.initApplicationEventMulticaster();this.onRefresh();this.registerListeners();this.finishBeanFactoryInitialization(beanFactory);this.finishRefresh();} catch (Error | RuntimeException var12) {if (this.logger.isWarnEnabled()) {this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var12);}this.destroyBeans();this.cancelRefresh(var12);throw var12;} finally {contextRefresh.end();}} finally {this.startupShutdownThread = null;this.startupShutdownLock.unlock();}}

四、各步骤详解

1. prepareRefresh():刷新前准备

  • 设置启动时间
  • 初始化 active 标志位
  • 初始化 PropertySources(环境变量、配置文件等)
  • 校验必须的配置

作用:确保上下文环境准备好,避免启动中途缺配置。


2. obtainFreshBeanFactory():获取 BeanFactory

整体流程
AbstractRefreshableApplicationContext#obtainFreshBeanFactory() -->AbstractRefreshableApplicationContext#refreshBeanFactory -->createBeanFactory() -->loadBeanDefinitions()
在这里插入图片描述
最后执行AnnotationConfigWebApplicationContext#loadBeanDefinitions(刷新上下文最核心的方法)

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) {AnnotatedBeanDefinitionReader reader = this.getAnnotatedBeanDefinitionReader(beanFactory);ClassPathBeanDefinitionScanner scanner = this.getClassPathBeanDefinitionScanner(beanFactory);BeanNameGenerator beanNameGenerator = this.getBeanNameGenerator();if (beanNameGenerator != null) {reader.setBeanNameGenerator(beanNameGenerator);scanner.setBeanNameGenerator(beanNameGenerator);beanFactory.registerSingleton("org.springframework.context.annotation.internalConfigurationBeanNameGenerator", beanNameGenerator);}ScopeMetadataResolver scopeMetadataResolver = this.getScopeMetadataResolver();if (scopeMetadataResolver != null) {reader.setScopeMetadataResolver(scopeMetadataResolver);scanner.setScopeMetadataResolver(scopeMetadataResolver);}if (!this.componentClasses.isEmpty()) {if (this.logger.isDebugEnabled()) {this.logger.debug("Registering component classes: [" + StringUtils.collectionToCommaDelimitedString(this.componentClasses) + "]");}reader.register(ClassUtils.toClassArray(this.componentClasses));}if (!this.basePackages.isEmpty()) {if (this.logger.isDebugEnabled()) {this.logger.debug("Scanning base packages: [" + StringUtils.collectionToCommaDelimitedString(this.basePackages) + "]");}scanner.scan(StringUtils.toStringArray(this.basePackages));}

主要流程

  1. 执行this.createBeanFactory()默认bean工厂:DefaultListableBeanFactory实例创建
  2. 从核心触发loadBeanDefinitions触发:创建对应的 BeanDefinition 将其注册到 BeanDefinitionRegistry
    • AnnotatedBeanDefinitionReader#register方法进行对@Component等注解进行解析注册成对应的 BeanDefinition (bean的元数据,包括bean名称,作用域等,类似注册bean之前得先准备好bean的材料,才能注册)
    • ClassPathBeanDefinitionScanner#scan方法对 @ComponentScan的basepack进行解析,扫描包路径下的注解注册BeanDefinition。
  3. 返回对应的DefaultListableBeanFactory工厂实例

3. prepareBeanFactory():BeanFactory 预准备

在这里插入图片描述

4. postProcessBeanFactory():子类扩展

添加相关 Bean 后处理器,为后续创建好的 bean 可做扩展。

5. invokeBeanFactoryPostProcessors():调用 BeanFactory 后置处理器

  • 先执行 BeanDefinitionRegistryPostProcessor(可修改 Bean 定义)
  • 再执行 BeanFactoryPostProcessor(可修改 BeanFactory 配置)

典型例子:
ConfigurationClassPostProcessor

  • 会解析 @Configuration 类:
  • 处理 @Bean 方法 → 新注册对应的 BeanDefinition
  • 处理 @ComponentScan → 扫描新包,注册新 BeanDefinition
  • 处理 @Import、@ImportResource → 引入额外 BeanDefinition,Import其实也是自动装配原理的第一个最重要的一点
    流程是
refresh()→ invokeBeanFactoryPostProcessors()中的postProcessBeanDefinitionRegistry()→ ConfigurationClassPostProcessor#processConfigBeanDefinitions()→ ConfigurationClassParser#parse→ ConfigurationClassParser#processImports()→ AutoConfigurationImportSelector#selectImports()

6. registerBeanPostProcessors():注册 Bean 后置处理器

  • AOP、@Autowired、@ConfigurationProperties 等功能都依赖它
  • 会在 Bean 实例化前后执行拦截逻辑

7. initMessageSource():国际化

  • 如果用户定义了 messageSource Bean,则使用用户的
  • 否则创建 DelegatingMessageSource 作为默认实现

8. initApplicationEventMulticaster():事件广播器

  • 如果用户定义了 applicationEventMulticaster,则使用用户的
  • 否则创建默认的 SimpleApplicationEventMulticaster

9. onRefresh():子类刷新逻辑

  • Web 环境下启动 Tomcat/Jetty/Undertow 内嵌容器
  • 加载 DispatcherServlet 等 MVC 核心组件

10. registerListeners():注册监听器

  • 注册所有 ApplicationListener 类型的 Bean
  • 处理启动前缓存的早期事件

11. finishBeanFactoryInitialization():根据实例化所有非懒加载单例

  • 根据已有的 BeanDefinition 注册对应的bean
  • 依赖注入
  • 初始化方法执行(@PostConstructInitializingBean 等)

12. finishRefresh():收尾工作

  • 清理缓存
  • 发布 ContextRefreshedEvent
  • 标记启动完成

五、流程图

prepareRefresh()↓
obtainFreshBeanFactory()↓
prepareBeanFactory()↓
postProcessBeanFactory()↓
invokeBeanFactoryPostProcessors()↓
registerBeanPostProcessors()↓
initMessageSource()↓
initApplicationEventMulticaster()↓
onRefresh()↓
registerListeners()↓
finishBeanFactoryInitialization()↓
finishRefresh()

六、总结

refresh() 就像 Spring Boot 启动的总指挥,控制了从配置准备 → BeanFactory 构建 → Bean 创建 → 事件发布的全流程。
理解它,不仅能帮助我们定位启动问题,还能在做框架扩展、定制化 Bean 加载逻辑时得心应手。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/92601.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/92601.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

关于过滤器(Filter)的学习

过滤器(Filter)概述 过滤器是 Java Servlet 规范的一部分,用于在请求到达 Servlet 之前或响应返回客户端之前拦截请求和响应。它可以用于执行各种任务,如请求预处理、响应后处理、身份验证、日志记录等。 过滤器的作用 预处理请…

Spring AI 打造智能面试人实战

Spring AI人工智能面试机器人相关实例 以下是与Spring AI人工智能面试机器人相关的实用案例,涵盖技术实现、功能设计及常见问题解决方案,按应用场景分类呈现: 技术集成案例 调用Hugging Face模型库处理专业领域问题 通过Spring Security添加面试会话身份验证 结合WebSoc…

QT 程序发布时候调用自定义动态库

1、需要在pro文件中增加下面的内容:QMAKE_LFLAGS "-Wl,-rpath,\\$$ORIGIN\" QMAKE_LFLAGS "-Wl,-rpath,\\$$ORIGIN/lib\" QMAKE_LFLAGS "-Wl,-rpath,\\$$ORIGIN/../lib\"其中lib为动态库的文件夹名称,可以根据自己喜好…

SpringBoot学习日记 Day6:解锁微服务与高效任务处理

一、开篇:从单体到微服务的思维转变刚开始接触微服务时,我总习惯把所有功能写在一个项目里。直到项目越来越臃肿,每次修改都要全量部署,才意识到微服务架构的价值。今天我们就来探索SpringBoot在微服务场景下的强大能力&#xff0…

机械学习--DBSCAN 算法(附实战案例)

DBSCAN 算法详解DBSCAN(Density-Based Spatial Clustering of Applications with Noise,带噪声的基于密度的空间聚类应用)是一种经典的密度聚类算法,由 Martin Ester 等人于 1996 年提出。与 K-means 等基于距离的聚类算法不同&am…

【昇腾】基于RK3588 arm架构Ubuntu22.04系统上适配Atlas 200I A2加速模块安装EP模式下的驱动固件包_20250808

一、背景 1.1 主要的硬件是:1.2 主要的软件是: RK3588跑操作系统Atlas 200I A2加速模块作为EP模式关键参数版本说明CPU架构aarch64OS版本Ubuntu 22.04.5 LTSkernel版本5.10.198 二、适配 准备固件run包文件:Ascend-hdk-310b-npu-firmware_7.…

如何在 VS Code 中进行 `cherry-pick`

cherry-pick 是 Git 的一个功能,允许你选择某个 commit 并将其应用到当前分支,而无需合并整个分支。在 VS Code 中,你可以通过 内置的 Git 功能 或 终端 来完成 cherry-pick。方法 1:使用 VS Code 的 Git 图形界面(GUI…

STM32CubeMX(十三)FatFs文件系统(SPI驱动W25Qxx)

目录 一、知识点 1. 什么是Fatfs文件系统? 2. Fatfs操作系统控制流程 二、实战操作 1.CubeMX配置 2. 配置串口以及SPI 3. 修改功能映射接口 4. 添加测试代码 5. 实验现象 在完成本章之前需要完成一些基础配置,详情查看下面的文章。 STM32CubeMX(二)新建工…

【前端后端部署】将前后端项目部署到云服务器

更多笔记在这里☞ 全栈之路: https://gitee.com/oldbe/notes 【跳转到】 觉得有用请点个 star ,非常感谢! 现在AI太强大,开发个人产品的门槛和成本太低了,只要你有好的想法都可以很快速的开发一款产品 1.…

vue如何监听localstorage

在Vue中监听localStorage的变化可以通过几种方式实现,但需要注意的是,localStorage本身不提供原生的事件监听机制,如DOM元素的MutationObserver。不过,你可以通过一些间接的方法来监听localStorage的变化。方法1:使用w…

灰狼算法+四模型对比!GWO-CNN-LSTM-Attention系列四模型多变量时序预测

摘要:聚划算!大对比!灰狼算法四模型对比!GWO-CNN-LSTM-Attention系列四模型多变量时序预测,该代码特别适合需要横向对比不同深度学习模型性能的时序预测场景,研究者可通过参数快速适配不同预测需求&#xf…

冒泡排序实现以及优化

一,冒泡排序说明冒泡排序是从第一个元素开始和后面一个元素进行判断是否满足左小右大,如果不满足就交换位置,再拿第二个和第三个进行上述操作一直到第n-1和第n个。经过上述的一轮操作就可以把第一个最大值放到最右边,在进行n轮上述…

水下管道巡检机器人cad【10张】三维图+设计说明书

摘 要 水下管道是水下油气管道的生命线,水下管道巡检机器人可以替代人工完成水下油气管道状态的实时监测和数据反馈,有助于工作人员对水下油气管道的运行情况实时掌握。 本文完成了水下管道巡检机器人的总体设计,采用三维设计软件Solidwor…

SQL(结构化查询语言)的四大核心分类

这张图展示了 SQL(结构化查询语言)的四大核心分类,分别对应不同的数据库操作场景。以下是逐类解析:1. 数据操作语言(DML:Data Manipulation Language)作用:用于操作数据库中的数据&a…

AI(1)-神经网络(正向传播与反向传播)

🍋🍋AI学习🍋🍋🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言📝支持一下博主…

嵌入式Linux学习 - 数据结构6

五、哈希表1. 哈希算法将数据通过哈希算法映射成一个键值,存取都在同一位置实现数据的高效存储和查找将时间复杂度尽可能降低至O(1)2. 哈希碰撞多个数据通过哈希算法得到的键值相同,称为产生哈希碰撞3. 哈希表构建哈希表存放0-100之间的数据将0 - 100之间…

GitHub 趋势日报 (2025年08月07日)

📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图1894nautilus_trader354stagehand315openai-cookbook263sim242ollama230prisma154v…

android 使用openimagelib OpenImage 实现点击放大图片,浏览

在 Android 中使用 OpenImageLib(假设这是一个开源图片加载库,类似于 Glide 或 Picasso)实现 点击放大图片并浏览 的功能,通常需要结合 图片查看器库(如 PhotoView)和 图片加载库(如 OpenImageLib)。以下是完整的实现方案: 1. 添加依赖 (1) 添加 OpenImageLib 依赖 …

计算机视觉CS231n学习(4)

深度学习软件 (这一部分去看tensorflow和pytorch的笔记) (见专栏)tensorflow和pytorch区别 tensorflow,我们先构建显示的图,然后重复运行它 pytorch,我们每次做前向传播时,都构建一个…

【具身智能】具身智能的革命——人形机器人如何重塑人类日常生活

还在为高昂的AI开发成本发愁?这本书教你如何在个人电脑上引爆DeepSeek的澎湃算力! 2025年被誉为具身智能的元年,人形机器人技术迅猛发展,将深刻改变人类生活方式。本文从具身智能的核心概念入手,探讨人形机器人的硬件架构、感知系统、运动控制和决策算法等技术基础。结合…