Spring上下文生命周期

news2024/9/21 16:35:40

基于入口来分析

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.上下文中注册bean
        configApplicationContext.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方法中设置断点。处理如下注解

  1. @Configuration
  2. @Component
  3. @PropertySource
  4. @PropertySources
  5. @ComponentScan
  6. @ComponentScans
  7. @Import
  8. @ImportResource
  9. @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 {
            // 发布关闭事件ContextClosedEvent
            publishEvent(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);
        }

        // 标记活动状态为:false
        this.active.set(false);
    }
}

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

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

相关文章

飞行机器人专栏(十)-- 异构多视角视觉系统

感知系统架构为满足天空端主控制器的诸如RGB-D图像处理等大容量数据吞吐、高速并行计算、实时运动控制以及通信和可视化任务的计算算力需求&#xff0c;同时优化功耗表现&#xff0c;采用了结构紧凑、功耗表现优异的边缘计算硬件NVIDA IJetson AGXOrin 。该开发者套件包含高性能…

Python学习笔记202302

1、numpy.empty 作用&#xff1a;根据给定的维度和数值类型返回一个新的数组&#xff0c;其元素不进行初始化。 用法&#xff1a;numpy.empty(shape, dtypefloat, order‘C’) 2、logging.debug 作用&#xff1a;Python 的日志记录工具&#xff0c;这个模块为应用与库实现了灵…

可用于标记蛋白质216699-36-4,6-ROX,SE,6-羧基-X-罗丹明琥珀酰亚胺酯

一.6-ROX&#xff0c;SE产品描述&#xff1a;6-羧基-X-罗丹明琥珀酰亚胺酯&#xff08;6-ROX&#xff0c;SE&#xff09;是一种用于寡核苷酸标记和自动DNA测序的荧光染料&#xff0c;可用于标记蛋白质&#xff0c;寡核苷酸和其他含胺分子的伯胺&#xff08;-NH2&#xff09;。西…

Git中遇到的问题

文章目录Clone克隆bytes of body are still expectedunable to access此文章是自己在Git操作时遇到的问题&#xff0c;先开个坑记录下来&#xff0c;如果以后还遇到了Git上的其他问题&#xff0c;会在后面进行添加。Clone克隆 bytes of body are still expected Clone失败信息…

【Redis】Java客户端JedisSpringDataRedis入门(三)

&#x1f697;Redis学习第三站~ &#x1f6a9;起始站&#xff1a;【Redis】概述&环境搭建(一) &#x1f6a9;本文已收录至专栏&#xff1a;数据库学习之旅 &#x1f44d;希望您能有所收获 在上一篇中我们学习了Redis常见命令的使用&#xff0c;显然&#xff0c;我们不可能一…

Day21【元宇宙的实践构想07】—— 元宇宙与人工智能

&#x1f483;&#x1f3fc; 本人简介&#xff1a;男 &#x1f476;&#x1f3fc; 年龄&#xff1a;18 &#x1f91e; 作者&#xff1a;那就叫我亮亮叭 &#x1f4d5; 专栏&#xff1a;元宇宙 0.0 写在前面 “元宇宙”在2021年成为时髦的概念。元宇宙到底是什么&#xff1f;元宇…

[架构之路-123]-《软考-系统架构设计师》-操作系统-2-操作系统原理 - 存储层次结构与存储管理(寄存器、Cache、MMU、内存、外存、页表)

前言&#xff1a;操作系统的本质就是创建一个并发的应用程序执行的环境&#xff0c;使得各种应用程序可以动态、共享相同的计算机物理硬件资源&#xff0c;计算机的三大物理资源包括&#xff1a;CPU内存外设应用程序&#xff08;管理应用程序&#xff09;&#xff1a;以进程和现…

线性代数学习-1

线性代数学习-1行图像和列图像行图像列图像总结本文转载于https://herosunly.blog.csdn.net/article/details/88698381 该文章本人认为十分有用&#xff0c;便自己敲一遍笔记加固印象原文链接 原文这个笔记感觉比我老师讲的更加透彻&#xff0c;清晰。很好的展示了线性代数的原…

【MySQL】数据库中锁和事务的相关知识点

1.事务的四大特点 原子性&#xff1a;事务中的所有操作要么都成功&#xff0c;要么都失败。所有的操作是一个不可分割的单位。一致性&#xff1a;一致性指的是事务执行前后&#xff0c;数据从一个合法性状态转移到另一个合法性状态。这个状态和业务有关&#xff0c;是自己定义…

基于ssm框架大学生社团管理系统(源码+数据库+文档)

一、项目简介 本项目是一套基于ssm框架大学生社团管理系统&#xff0c;主要针对计算机相关专业的正在做bishe的学生和需要项目实战练习的Java学习者。 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目可以直接作为bishe使用。 项目都经过严格调试&#xff0c;确保可…

在线文本翻译能力新增14个直译模型,打造以中文为轴心语言的翻译系统

经济全球化的今天&#xff0c;人们在工作和生活中经常会与外语打交道。相较传播性较广的英语而言&#xff0c;其他语种的识别和阅读对大多数人来说是一件难事&#xff0c;此时就需要借助语言翻译软件来帮助理解。 华为 HMS Core 机器学习服务&#xff08;ML Kit&#xff09;翻…

JVM详解——内存结构

文章目录内存结构1、 运行时数据区2、虚拟机栈3、本地方法栈4、程序计数器5、 堆6、方法区7、运行时常量池8、内存溢出和内存泄漏9、 堆溢出内存结构 1、 运行时数据区 Java虚拟机在运行Java程序期间将管理的内存划分为不同的数据区&#xff0c;不同的区域负责不同的职能&…

[YOLO] yolo理解博客笔记

YOLO v2和V3 关于设置生成anchorbox&#xff0c;Boundingbox边框回归的过程详细解读 YOLO v2和V3 关于设置生成anchorbox&#xff0c;Boundingbox边框回归的个人理解https://blog.csdn.net/shenkunchang1877/article/details/105648111YOLO v1网络结构计算 Yolov1-pytorch版 …

ChatGPT修炼指南和它的电力畅想

近期&#xff0c;ChatGPT刷屏各大社交平台&#xff0c;无疑成为人工智能界最靓的仔&#xff01; 身为一款“会说话”的聊天机器人程序&#xff0c;它与前辈产品Siri、小度、微软小冰等有什么不同&#xff1f;先来听听小伙伴们怎么说。 ChatGPT何以修炼得这么强大&#xff1f;…

什么叫骨传导概念耳机,骨传导耳机的原理是什么

骨传导耳机在蓝牙耳机当中是属于十分特殊传输声音的一种方式&#xff0c;开放式传输声音&#xff0c;其使用优点也受到越来越多人的熟知和喜爱&#xff0c;但还有一部分朋友们不知道骨传导耳机传输声音的原理是啥&#xff0c;下面就给大家简单科普一下。骨传导耳机是利用内置的…

BurpSuite实战教程03-BurpSuite插件开发

burp插件开发 Burp Suite的强大除了自身提供了丰富的可供测试人员使用的功能外&#xff0c;其提供的支持第三方拓展插件的功能也极大地方便使用者编写自己的自定义插件。&#xff0c;Burp Suite支持的插件类型有Java、Python、Ruby三种。无论哪种语言的实现&#xff0c;开发者…

华为造车锚定智选模式, 起点赢家赛力斯驶入新能源主航道

文|螳螂观察 作者| 易不二 近日&#xff0c;赛力斯与华为的一纸联合业务深化合作协议&#xff0c;给了频频猜测赛力斯与华为之间关系的舆论一个明确的定调&#xff1a;智选模式已成为华为与赛力斯共同推动中国新能源汽车产业高质量发展的坚定选择。 自华为智能汽车业务开启零…

【Java】TCP网络编程(字节/符流)

文章目录概念TCP网络编程ServerSocketsocket使用区别和原理演示概念 TCP&#xff08;传输控制协议&#xff09;是一种面向连接的协议&#xff0c;用于在计算机网络中可靠地传输数据。TCP是Internet协议族中的一个核心协议&#xff0c;它在传输层提供可靠、有序、基于流的传输服…

影视网络U盘系统开发思路

由于光纤入户千兆宽带的普及&#xff0c;在用户侧的下载速度得到前所未有的提高。与此同时&#xff0c;用户对于高清视频的需求日益增强&#xff0c;原有的视频点播系统在传输高清视频码流上时有卡顿现象发生&#xff0c;这严重影响了用户的娱乐体验。现时&#xff0c;大部分用…

IOS逆向之frida安装

首先手机要越狱&#xff0c;这个就不说了&#xff0c;博主就是咸鱼搞了个160的苹果6&#xff0c; 自己刷到苹果6支持最新的12.5.7版本后越狱&#xff1b; 谁让他低版本&#xff0c;不支持 CrackerXI砸壳呢&#xff0c;当时你要是使用 frida-ios-dump 也是可以的&#xff1b; …