当前位置: 首页 > news >正文

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方法中设置断点。处理如下注解

  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 {// 发布关闭事件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);}
}
http://www.lryc.cn/news/24014.html

相关文章:

  • GitHub 标星 15w,如何用 Python 实现所有算法?
  • LeetCode 700. 二叉搜索树中的搜索
  • 【数据结构】树与二叉树
  • Stress压力工具的部署及使用
  • [蓝桥杯 2020 省 AB3] 乘法表
  • Python基础知识
  • FME案例实战教程:聚焦实战应用,摆脱思路束缚,您值得拥有
  • 【JavaScript】根据元素内容遍历元素的方案
  • kafka全解
  • (三)随处可见的LED广告屏是怎么工作的呢?接入GUI
  • 线程池简介
  • 大数据面试题集锦-Hadoop面试题(四)-YARN
  • Python---time模块
  • 坚鹏:学习贯彻二十大精神 解码共同富裕之道(面向银行)
  • python查看程序的cpu和内存资源占用情况
  • 番外10:使用ADS对射频功率放大器进行非线性测试2(使用带宽20MHz的64QAM信号进行ACLR、EVM、CCDF测试)
  • Ubuntu搭建maven私服
  • 【JavaWeb】Servlet基础
  • pinia + pinia-plugin-persistedstate + 组合式API 写法,持久化失效问题
  • ptrace 调式详解
  • 【AI绘画】绝美春天插画,人人都是插画师
  • 蓝桥杯入门即劝退(二十四)重复的子字符串(被秒杀)
  • 针对序列级和词元级应用微调BERT(需修改)
  • (四十七)大白话表锁和行锁互相之间的关系以及互斥规则是什么呢?
  • 织梦TXT批量导入TAG标签并自动匹配相关文章插件
  • Sentinel架构篇 - 10分钟带你看滑动窗口算法的应用
  • redis主从复制
  • 近期常见组件漏洞更新:
  • 深度学习常用的激活函数总结
  • Java编程问题top100---基础语法系列(二)