Spring IOC - Spring启动过程解析

        Spring启动流程的核心逻辑主要体现在方法AbstractApplicationContext#refresh中,该方法没有被子类重写。

        本文主要从宏观层面对其进行剖析,从整体上感知。各执行步骤和作用按先后顺序如下表所示,其中标红方法为核心方法标绿色方法提供了扩展点。

方法名

主要作用

prepareRefresh()

记录容器启动时间、设置容器状态;提供扩展点用于自定义添加key-value属性

obtainFreshBeanFactory()

获取一个新鲜的beanFactory实例,该方法由两个子类实现:

1.GenericApplicationContext:很简单,返回无参构造方法创建的beanFactory

2.AbstractRefreshableApplicationContext:关闭当前beanFactory,创建新的beanFactory,体现了刷新的含义

prepareBeanFactory(beanFactory)

提前给beanFactory塞入bean实例:如BeanFactory,ResourceLoader等,以及设置类加载器、属性编辑器等

postProcessBeanFactory(beanFactory)

此处是Spring留的扩展点,目的是在beanFactory准备好后,留给用户最后对beanFactory做一些设置

如对于Web应用,重写后给beanFactory塞入ServletContext等单例bean

invokeBeanFactoryPostProcessors(beanFactory)

调用BeanFactoryPostProcessor的实现类对BeanFactory进行后置处理,如调用ConfigurationClassPostProcessor对常用注解进行解析,生成BeanDefinition

registerBeanPostProcessors(beanFactory)

注册Bean的后置处理器,包括系统内置的和自定义的,如:AutowireAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor

initMessageSource()

初始化MessageSource,用于支持国际化

initApplicationEventMulticaster()

初始化事件派发器,用于支持事件监听

onRefresh()

Spring提供的扩展点,留给子类实现

registerListeners()

注册事件监听器

finishBeanFactoryInitialization(beanFactory)

实例化所有非懒加载的单例Bean,Spring Bean的生命周期就是从这里开始的

finishRefresh()

完成刷新,发布容器刷新完成事件等

        源码及注释如下:

	// Spring应用上下文的核心方法,它负责完成Spring容器的初始化和刷新工作@Overridepublic void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {// Prepare this context for refreshing.// 准备刷新操作,包括记录容器启动时间、设置容器状态、获取属性、验证必要的属性prepareRefresh();// Tell the subclass to refresh the internal bean factory.// 获取一个新鲜的BeanFactory实例,该方法由子类实现// 获取新的beanFactory,销毁原有beanFactory、为每个bean生成BeanDefinition等,注意,此处是获取新的,销毁旧的,这就是刷新的意义ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// Prepare the bean factory for use in this context.// 对BeanFactory进行一些设置,例如设置类加载器、添加属性编辑器等prepareBeanFactory(beanFactory);try {// Allows post-processing of the bean factory in context subclasses.// 允许子类在BeanFactory标准初始化完成后对其进行进一步的处理// 此处是spring留的扩展点,目前是在beanFactory准备好后,留给用户最后对beanFactory做一些设置// 可参考GenericWebApplicationContext#postProcessBeanFactory实现postProcessBeanFactory(beanFactory);// Invoke factory processors registered as beans in the context.// 调用BeanFactoryPostProcessor的实现类对BeanFactory进行后置处理// 扫描解析的核心代码invokeBeanFactoryPostProcessors(beanFactory);// Register bean processors that intercept bean creation.// 注册BeanPostProcessor的实现类,用于在Bean创建过程中进行拦截registerBeanPostProcessors(beanFactory);// Initialize message source for this context.// 初始化MessageSource,用于支持国际化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.// 实例化所有非懒加载的单例Bean// 这一步可谓和我们开发者打交道最多,我们自定义的Bean绝大多都是在这一步被初始化的,包括依赖注入等等// 因此了解这一步,能让我们更深入的了解Spring是怎么管理我们的Bean的生命周期,以及依赖关系的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.// 如果在刷新过程中出现异常,会执行该方法取消操作,并销毁已经创建的单例Bean,最后,会重置Spring核心中的一些缓存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();}}}

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

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

相关文章

[GDOUCTF 2023]<ez_ze> SSTI 过滤数字 大括号{等

SSTI模板注入-中括号、args、下划线、单双引号、os、request、花括号、数字被过滤绕过(ctfshow web入门370)-CSDN博客 ssti板块注入 正好不会 {%%}的内容 学习一下 经过测试 发现过滤了 {{}} 那么我们就开始吧 我们可以通过这个语句来查询是否存在ss…

免费亲人微信聊天记录提取软件新版本v1.1,使用说明,注意事项 2023.11.06

V 1.1 优化了备份速度,新增了备份消息类型的选型,可以选择仅仅备份文本,或者文本与音频,或者文本音频视频图片。 有什么办法可以导出与某个人的微信聊天记录? 只想导出与某个微信好友的聊天记录,有办法做到…

内网服务器(不通外网)访问高德在线地图服务的方法

在项目部署过程中,若部署服务器处于内网环境,则无法调用高德服务。需要通过搭建代理实现请求的转发,从而获取到在线服务内容。下面的记录解决了内网服务器访问高德地图服务的问题。 一、所需设备 内网服务器(项目所需部署环境&a…

运维知识点-MySQL从小白到入土

MySQL从小白到入土 mysql 服务器安装windows mysql 服务漏洞复现-mysql jdbc反序列化-权限绕过 mysql 服务器安装 https://dev.mysql.com/downloads/mysql/https://www.cnblogs.com/xiaostudy/p/12262804.html 点餐小程序腾讯云服务器安装mysql8 windows mysql 服务 net sta…

1.UML面向对象类图和关系

文章目录 4种静态结构图类图类的表示类与类之间的关系依赖关系(Dependency)关联关系(Association)聚合(Aggregation)组合(Composition)实现(Realization)继承/泛化(Inheritance/Generalization)常用的UML工具reference欢迎访问个人网络日志🌹🌹知行空间🌹🌹 4种静态结构…

cp没有--exclude选项!Linux复制文件夹时如何排除一些文件?

之前使用tar命令压缩文件将时,使用了–exclude选项排除了一些不需要的文件。现在我想复制一个文件夹,但是其中一些文件不需要复制,此时注意到cp命令居然没有–exclude选项。 rsync可以快速地帮助我们完成相同的事情,命令如下&…

rust 基础数据类型

默认类型 大部分情况下,rust 可以基于上下文自动推导出变量的类型。下面代码中,变量 x 没有显式,rust 默认是 i32 类型。 fn main() {let x 5; }但也有一些例外情况,比如,字符串类型的转换中变量 x 的类型&#xff…

【Java 进阶篇】JSP 简单入门

在现代Web开发中,JavaServer Pages(JSP)是一项非常重要的技术。JSP允许开发者将Java代码嵌入HTML页面,以实现动态内容的生成和呈现。本文将详细介绍JSP的概念、原理以及如何使用JSP来构建Web应用程序。 第一部分:JSP …

如何将 XxlJob 集成达梦数据库

1. 前言 在某些情况下,你的项目可能会面临数据库选择的特殊要求,随着国产化的不断推进,达梦数据库是一个常见的选择。本篇博客将教你如何解决 XxlJob 与达梦数据库之间的 SQL 兼容性问题,以便你的任务调度系统能够在这个数据库中…

章鱼网络进展月报 | 2023.10.1-10.31

章鱼网络大事摘要 1、Louis 成功竞选 NDC 的 HoM 议席,将会尽最大努力推动 NEAR 变革。2、章鱼网络受邀参加在土耳其主办的 Cosmoverse2023,分享 Adaptive IBC 的技术架构。3、2023年10月8日章鱼日,是章鱼网络主网上线2周年的纪念日。 …

机器学习---SVM目标函数求解,SMO算法

1. 线性可分支持向量机 1.1 定义输入数据 假设给定⼀个特征空间上的训练集为: 其中,(x , y )称为样本点。 x 为第i个实例(样本)。 y 为x 的标记: 当y 1时,x 为正例;当y −1时,x…

vue3项目实践

创建 vue3 项目 node本版:node 16.x.x, 脚手架:create-vue 脚手架工具,底层vite 创建vue3项目:npm init vuelatest setup函数 vue3 单文件组件 1、vite.config.js配置文件基于vite的配置 2、template模板不再要求唯…

NOIP2023模拟10联测31 游戏

题目大意 Alice \text{Alice} Alice和 Bob \text{Bob} Bob在玩一个游戏:有一个由正整数组成的集合 S S S,两人轮流从中选数, Alice \text{Alice} Alice先手。每次一个人可以从当前集合中选一个数 x x x,把 x x x以及 x x x在集合中…

docker compose实现容器编排

Compose 使用的三个步骤: 使用 Dockerfile 定义应用程序的环境 使用 compose.yml 定义构成应用程序的服务,这样它们可以在隔离环境中一起运行 最后,执行 docker compose up 命令来启动并运行整个应用程序 为什么需要docker compose Dock…

使用VBA打印PDF文件

使用VBA打印工作表和工作簿文件都很容易实现,但是有时需要使用VBA打印已经保存在本机的其他文件,例如PDF文件格式的账单,如果这个PDF并非由Excel生成的那么就无法使用前述方法实现。 调用Windows的Shell命令可以实现打印PDF文件。 示例代码…

万宾科技管网水位监测助力智慧城市的排水系统

以往如果要了解城市地下排水管网的水位变化,需要依靠人工巡检或者排查的方式,这不仅加大了人员的工作量,而且也为市政府带来了更多的工作难题。比如人员监管监测不到位或无法远程监控等情况,都会降低市政府对排水管网的管理能力&a…

SpringBoot配置文件优先级

1.idea临时属性 说明:Program arguments配置--server.port8082 --ab;意思是将端口改成了8082。这个优先级最高。 2.resource 说明:创建config文件里面的yml文件。 3.jar包同级(yml) 说明:创建一个yml文件…

如何去除视频水印?三种简便有效的方法解决视频水印问题

在当今社交媒体时代,视频分享已成为一种流行趋势。然而,很多人在分享自己的作品时却苦于视频上存在的水印,水印通常是出于版权保护或品牌推广的目的而添加到视频中的,但有时它们可能会对用户体验造成负面影响。 如果您正在寻找如何…

golang gorm通过泛型实现通用单表增删改

golang gorm通过泛型实现通用单表增删改 无废话,直接上代码 想实现通用,首先得实现查询的通用,可以用传递map实现 func Where(where map[string]interface{}) func(db *gorm.DB) *gorm.DB {return func(db *gorm.DB) *gorm.DB {dbTmp : db…

Linux 脚本周期性监控进程是否存在,不存在就启动

以监控节点上的“Elasticsearch”进程为例,下面的脚本实现了周期性监控该进程是否存在,不存在就执行对应命令启动进程功能。 #!/bin/bash# 设置要检查的进程名称 PROCESS_NAME"Elasticsearch"# 定义一个函数来检查进程是否运行 check_process…