Spring上下文生命周期
基于入口来分析
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;@Configuration
@ComponentScan
public class MainConfig {public static void main(String[] args) {//1.创建spring上下文AnnotationConfigApplicationContext configApplicationContext = new AnnotationConfigApplicationContext();//2.上下文中注册beanconfigApplicationContext.register(MainConfig.class);//3.刷新spring上下文,内部会启动spring上下文configApplicationContext.refresh();//4.关闭spring上下文System.out.println("stop ok!");configApplicationContext.close();}
}
创建Spring应用上下文

AnnotatedBeanDefinitionReader
用来读取及注册通过注解方式定义的bean
ClassPathBeanDefinitionScanner
bean定义扫描器,可以扫描包中的类,对满足条件的类,会将其注册到spring容器中
ConfigurationClassPostProcessor
负责所有bean的注册,如果想看bean注册源码的,可以在其postProcessBeanDefinitionRegistry方法中设置断点。处理如下注解
- @Configuration
- @Component
- @PropertySource
- @PropertySources
- @ComponentScan
- @ComponentScans
- @Import
- @ImportResource
- @Bean
org.springframework.context.annotation.AnnotatedBeanDefinitionReader#registerBean(java.lang.Class<?>)
AutowiredAnnotationBeanPostProcessor
负责处理@Autowire注解
CommonAnnotationBeanPostProcessor
负责处理@Resource注解
EventListenerMethodProcessor
负责处理@EventListener标注的方法,即事件处理器
DefaultEventListenerFactory
负责将@EventListener标注的方法包装为ApplicationListener对象
AbstractApplicationContext#refresh
public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");/*** 阶段2:Spring应用上下文启动准备阶段* 1、切换到活动状态* 2、初始化PropertySource,留给子类去实现的,可以在这个方法中扩展属性配置信息,丢到this.environment中* 3、验证环境配置中是否包含必须的配置参数信息,* 4、存储存放早期的事件监听器、应用程序事件*/prepareRefresh();/*** 阶段3:BeanFactory创建阶段* 1、刷新BeanFactory,由子类实现* 2、返回spring上下文中创建好的BeanFacotry*/ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();/*** 阶段4:BeanFactory准备阶段* 1、设置类加载器* 2、设置SPEL表达式解析器:BeanExpressionResolver* 3、设置属性编辑注册器:PropertyEditorRegistrar* 4、添加BeanPostProcessor:ApplicationContextAwareProcessor,当自定义Bean实现了EnvironmentAware等接口时,进行接口方法回调赋值* 5、注册依赖注入的时候查找的对象:BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext* 6、添加BeanPostProcessor:ApplicationListenerDetector,处理自定义的事件监听器* 7、添加LoadTimeWeaver* 8、将Environment注册到spring容器,对应的bena名称是environment* 9、将系统属性注册到spring容器,对应的bean名称是systemProperties,对应 --> System.getProperties()启动参数,如-D参数=值* 10、将系统环境变量配置信息注入到spring容器,对应的bean名称是systemEnvironment,对应 --> System.getenv()获取环境变量信息的* 11、添加Bean:applicationStartup*/prepareBeanFactory(beanFactory);try {/*** 阶段5:BeanFactory后置处理阶段:允许在上下文子类中对 Bean 工厂进行后处理。* 此时beanFactory已经创建好了,但是容器中的bean还没有被实例化,子类可以实现这个方法,可以对BeanFactory做一些特殊的配置,* 比如可以添加一些自定义BeanPostProcessor等等,主要是留给子类去扩展的。*/postProcessBeanFactory(beanFactory);StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");/*** 阶段6:BeanFactory注册BeanPostProcessor阶段* 主要是从spring容器中找到BeanFactoryPostProcessor接口的所有实现类,然后调用,完成所有bean注册的功能,* 注意是bean注册,即将bean的定义信息转换为BeanDefinition对象,然后注册到spring容器中,此时bean还未被实例化。* 1、调用BeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry(依次从传的addBeanFactoryPostProcessor>实现了PriorityOrdered->Order->其他)* spring中所有bean的注册都会在此阶段完成,按照规范,所有bean的注册必须在此阶段进行,其他阶段不要再进行bean的注册。* 2、调用BeanFactoryPostProcessor.postProcessBeanFactory* 到这个阶段的时候,spring容器已经完成了所有bean的注册,这个阶段中你可以对BeanFactory中的一些信息进行修改,比如修改阶段1中一些bean的定义信息,修改BeanFactory的一些配置等等*/invokeBeanFactoryPostProcessors(beanFactory);/*** 阶段7:注册BeanPostProcessor(bean后置处理器)* 这个阶段会遍历spring容器bean定义列表,把所有实现了BeanPostProcessor接口的bean撸出来,然后将他们添加到spring容器的BeanPostProcessor列表中。* 本质上就是执行:beanFactory.addBeanPostProcessor(postProcessor);* 1、注册了BeanPostProcessorChecker* 2、注册实现了BeanPostProcessor接口的Bean* 3、注册了ApplicationListenerDetector*/registerBeanPostProcessors(beanFactory);beanPostProcess.end();/*** 阶段8:初始化内建Bean:MessageSource是用来处理国际化的* 1、注册bean messageSource(可自定义)*/initMessageSource();/*** 阶段9:初始化内建Bean:Spring事件广播器* 1、注册bean applicationEventMulticaster(可自定义),也可自定义Executor*/initApplicationEventMulticaster();/*** 阶段10:Spring应用上下文刷新阶段,由子类实现初始化其他特殊 bean。*/onRefresh();/*** 阶段11:Spring事件监听器注册阶段,注册事件监听器到事件广播器中* 1、先注册静态指定的侦听器,即将spring上下文中添加的事件监听器,添加到事件广播器(ApplicationEventMulticaster阶段9)* 2、将spring容器中定义的事件监听器,添加到事件广播器(ApplicationEventMulticaster)中* 3、发布早期的事件*/registerListeners();/*** 阶段12:实例化所有剩余的(非lazy init)单例bean,不包需要延迟实例化的bean* 1、初始化conversionService转换服务* 2、添加${}表达式解析器,EmbeddedValueResolver* 3、早一些实例化LoadTimeWeaverAware类的Bean* 4、冻结所有bean定义,表示已注册的bean定义不会被进一步修改或后处理。这允许工厂主动缓存bean定义元数据。* 5、实例化所有单例bean(不包含需延迟实例化的bean),通常scope=singleton的bean都会在下面这个方法中完成初始化。beanFactory.preInstantiateSingletons();* 以下是beanFactory.preInstantiateSingletons();* 1、循环遍历beanNames列表,完成所有单例bean的实例化工作,这个循环完成之后,所有单例bean已经实例化完毕了,被放在spring容器缓存起来了。* 2、触发所有 bean 的初始化后回调...调用Bean实现了SmartInitializingSingleton接口的afterSingletonsInstantiated方法*/finishBeanFactoryInitialization(beanFactory);/*** 阶段13:刷新完成阶段,最后一步:发布相应的事件。* 1、清理一些资源缓存* 2、为此上下文初始化生命周期处理器,注册bena lifecycleProcessor spring应用上下文的生命周期处理器(可自定义)* 3、首先将刷新传播到生命周期处理器,执行LifecycleProcessor.onRefresh():从容器中找到所有实现Lifecycle接口的bean,然后调用他们的start方法。* 4、发布ContextRefreshedEvent事件,想在这个阶段做点事情的,可以监听这个事件。*/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.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();contextRefresh.end();}}}
Spring应用上下文关闭阶段

protected void doClose() {// 判断是不是需要关闭(active为tue的时候,才能关闭,并用cas确保并发情况下只能有一个执行成功)if (this.active.get() && this.closed.compareAndSet(false, true)) {if (logger.isDebugEnabled()) {logger.debug("Closing " + this);}if (!NativeDetector.inNativeImage()) {LiveBeansView.unregisterApplicationContext(this);}try {// 发布关闭事件ContextClosedEventpublishEvent(new ContextClosedEvent(this));}catch (Throwable ex) {logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);}// 执行生命周期处理器LifecycleProcessor.onClose():从容器中找到所有实现Lifecycle接口的bean,然后调用他们的stop方法。if (this.lifecycleProcessor != null) {try {this.lifecycleProcessor.onClose();}catch (Throwable ex) {logger.warn("Exception thrown from LifecycleProcessor on context close", ex);}}// 销毁上下文的BeanFactory中所有缓存的单例destroyBeans();// 关闭BeanFactory本身closeBeanFactory();// 就给子类去扩展的onClose();// 恢复事件监听器列表至刷新之前的状态,即将早期的事件监听器还原if (this.earlyApplicationListeners != null) {this.applicationListeners.clear();this.applicationListeners.addAll(this.earlyApplicationListeners);}// 标记活动状态为:falsethis.active.set(false);}
}
相关文章:
Spring上下文生命周期
基于入口来分析 import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration;Configuration ComponentScan public cl…...
GitHub 标星 15w,如何用 Python 实现所有算法?
学会了 Python 基础知识,想进阶一下,那就来点算法吧!毕竟编程语言只是工具,结构算法才是灵魂。 新手如何入门 Python 算法? 几位印度小哥在 GitHub 上建了一个各种 Python 算法的新手入门大全。从原理到代码…...
LeetCode 700. 二叉搜索树中的搜索
LeetCode 700. 二叉搜索树中的搜索 难度:easy\color{Green}{easy}easy 难度:middle\color{orange}{middle}middle 难度:hard\color{red}{hard}hard 题目描述 给定二叉搜索树(BST)的根节点 rootrootroot 和一个整数值…...
【数据结构】树与二叉树
目录 1、树的概念及结构 1.1、概念 1、树的特点 2、树与非树 1.2、概念 (重要) 1.3、树的表示形式 2、二叉树(重点) 2.1、概念 2.2、二叉树的特点 2.3、两种特殊的二叉树 1、满二叉树 2、完全二叉树 2.4、二叉树的性…...
Stress压力工具的部署及使用
Stress压力工具的部署及使用 下载地址:wget https://fossies.org/linux/privat/old/stress-1.0.5.tar.gz 1.部署 进入目录执行./autogen.sh [rootiZ2ze1pj93eyq389c2ppi5Z stress-1.0.5]# ./autogen.sh ps:如果执行过程中缺包,安装对应的…...
[蓝桥杯 2020 省 AB3] 乘法表
题目描述九九乘法表是学习乘法时必须要掌握的。在不同进制数下,需要不同的乘法表。例如, 四进制下的乘法表如下所示:1*11 2*12 2*210 3*13 3*212 3*321请注意,乘法表中两个数相乘的顺序必须为样例中所示的顺序,不能随意交换两个乘…...
Python基础知识
基础知识 基础知识包括输入输出、变量、数据类型、表达式、运算符这5个方面。 1.输入输出 Python有很多函数,后面我们会细讲,但这里先将两个最基本的函数:输入和输出。 输出函数print(),在前面我们已经用过了,语法…...
FME案例实战教程:聚焦实战应用,摆脱思路束缚,您值得拥有
一、教程链接(一)FME案例实战教程链接1.FME案例实战教程(完整版) ☚强烈推荐☚2.FME案例实战教程(A组)3.FME案例实战教程(B组)4.FME案例实战教程(C组)&#…...
【JavaScript】根据元素内容遍历元素的方案
▒ 目录 ▒🛫 导读需求1️⃣ jQuery2️⃣ XPATH(document.evaluate)3️⃣ 原生js(querySelectorAll & Array)🛬 文章小结📖 参考资料🛫 导读 需求 因业务需要,根据元…...
kafka全解
目录Kafka概述定义消息队列目录结构分析传统消息队列的应用场景消息队列的两种模式点对点模式发布/订阅模式Kafka基础架构Kafka快速入门安装部署集群规划集群部署集群启停脚本Kafka命令行操作Kafka基础架构主题命令行操作生产者命令行操作消费者命令行操作kafka可视化工具Kafka…...
(三)随处可见的LED广告屏是怎么工作的呢?接入GUI
续上文,本篇我们将尝试接入一个GUI来控制点阵屏。在前两篇中,我们相继介绍了点阵屏的控制原理,以及如何让点阵屏按照我们所想的进行显示。本篇将在此基础上接入一个GUI,使点阵屏的控制更加优雅。限于阅读体验和展示效果࿰…...
线程池简介
线程池 线程池(英语:thread pool):一种线程使用模式。线程过多会带来调度开销,进而影响缓存局部性和整体性能。而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务。这避免了在处理短时间任务时…...
大数据面试题集锦-Hadoop面试题(四)-YARN
你准备好面试了吗?这里有一些面试中可能会问到的问题以及相对应的答案。如果你需要更多的面试经验和面试题,关注一下"张飞的猪大数据分享"吧,公众号会不定时的分享相关的知识和资料。 文章目录1、为什么会产生 yarn,它解决了什么问题…...
Python---time模块
专栏:python 个人主页:HaiFan. 专栏简介:Python在学,希望能够得到各位的支持!!! time模块前言时间戳time.time()将时间戳转换成字符串time.ctime()将时间戳转换为元组time.localtime(时间戳)将元…...
坚鹏:学习贯彻二十大精神 解码共同富裕之道(面向银行)
学习贯彻二十大精神 解码共同富裕之道课程背景: 很多银行从业人员存在以下问题:不知道如何准确解读二十大精神?不清楚共同富裕相关政策要求?不知道如何有效推动共同富裕? 课程特色:有实战案例有…...
python查看程序的cpu和内存资源占用情况
1.获取线程消耗的内存 :线程内存使用的概念没有明确定义。线程共享它们的内存。唯一真正的线程本地内存是它的调用堆栈,除非您认真地递归地做一些事情,否则这不是有趣的部分。 2.获取进程消耗的内存 3.获取程序消耗的内存 mprof run endpoint.py 4.查看…...
番外10:使用ADS对射频功率放大器进行非线性测试2(使用带宽20MHz的64QAM信号进行ACLR、EVM、CCDF测试)
番外10:使用ADS对射频功率放大器进行非线性测试2(使用带宽20MHz的64QAM信号进行ACLR、EVM、CCDF测试) 1、基本理论 功率放大器的非线性性能十分重要,特别是对于当前广泛使用的移动设备。由于其各种复杂的信号调制,功…...
Ubuntu搭建maven私服
1.安装JDK8 已经是JDK8的需要配置环境变量,如果是更高版本的JDK则需要修改nexus配置文件 2.下载nexus安装包 百度网盘下载:链接:https://pan.baidu.com/s/1DfKqql8tZNQXEBxAEH7UyA 提取码:hx4p安装到有磁盘的目录如下所示&…...
【JavaWeb】Servlet基础
文章目录1.Tomcat服务器安装注意事项2.编写WebApp3.BS系统角色和协议4.模拟Servlet4.1模拟sun公司4.2模拟Tomcat服务器4.3模拟WebApp开发者5.开发一个带有Servlet的WebApp5.1创建一个名为crm的项目5.2 在项目中创建一个名为WEB-INF的文件(必须)5.3在WEB-…...
pinia + pinia-plugin-persistedstate + 组合式API 写法,持久化失效问题
持久化失效卡了一天的问题安装使用就不多说了,主要是针对持久化失效的几个问题说明和解决方法首先是组合式写法,配置持久化export const useUserStore defineStore(user, () > {},{persist: true} )defineStore 第三个参数,具体可以看 p…...
MPNet:旋转机械轻量化故障诊断模型详解python代码复现
目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...
TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
Admin.Net中的消息通信SignalR解释
定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...
centos 7 部署awstats 网站访问检测
一、基础环境准备(两种安装方式都要做) bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats࿰…...
家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南 在数字化营销时代,邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天,我们将深入解析邮件打开率、网站可用性、页面参与时…...
学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...
Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...
有限自动机到正规文法转换器v1.0
1 项目简介 这是一个功能强大的有限自动机(Finite Automaton, FA)到正规文法(Regular Grammar)转换器,它配备了一个直观且完整的图形用户界面,使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...
Caliper 配置文件解析:fisco-bcos.json
config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...
