Spring listener执行过程

news/2024/12/18 23:43:12/文章来源:https://www.cnblogs.com/euler-blog/p/18616070

Spring mvc项目通过listener初始化spring IOC容器过程

方法太多太深,没法一一追到位

graph TD; ContextLoaderListener#contextInitialized-->ContextLoader#initWebApplicationContext -->servletContext#getAttribute(获取servletContext中的org.springframework.web.context.WebApplicationContext.ROOT属性) -->success{判断这个属性是否为空} success-->|否|抛IllegalStateException异常 success-->|是|记录开始时间-->ContextLoader#context{判断ContextLoader#contwext是否为空}ContextLoader#context-->|空|createWebApplicationContext(为这个加载器实例化根WebApplicationContext) -->determineContextClass(确定ContextClass) --> BeanUtils.instantiateClass(创建一个ConfigurableWebApplicationContext对象即web容器) -->instantiateClass(通过这个工具使用无参构造器创建对象实例) -->ConfigurableWebApplicationContextContextLoader#context-->|不空|ConfigurableWebApplicationContext(判断这个容器是否为ConfigurableWebApplicationContext) -->设置该容器的parentContext为null -->configureAndRefreshWebApplicationContext(配置并刷新webApplicationContext) -->给这个root容器设置一个id -->setServletContext(把servletContext配置到WebApplicationContext中) -->getInitParameter#contextConfigLocation{获取servlet中的contextConfigLocation参数} -->|如果在servlet中设置了配置文件的路径|setConfigLocation(把该路径配置到webApplicatonContext中) -->获取webApplicationContext中的环境变量信息(getEnvironment) -->WebApplicationContextUtils.initServletPropertySources(初始化配置信息 这个对象是standardServletEnvironment中 这个其实就是读取指定的配置文件信息) -->指定servletContextInitParams对应的配置文件 -->指定servletConfigInitParams对应的配置文件 -->customizeContext(定制容器) -->determineContextInitializerClasses(确定容器初始化使用的ApplicationContextInitializer<ConfigurableApplicationContext>列表) -->走进determineContextInitializerClasses这个方法 -->获取参数{从servletContext容器中获取初始化参数#globalInitializerClasses} 获取参数-->|如果设置了ServletContextInitParameter之globalInitializerClasses|将该配置对应的字符串分解为独立的字符串并组成数组添加到返回值list中 -->再次获取参数{从servletContext容器中获取初始化参数#contextInitializerClasses} 再次获取参数-->|如果设置了ServletContextInitParameter之contextInitializerClasses|将该配置对应的字符串分解为独立的字符串并组成数组再次添加到返回值list中 -->返回列表并结束determineContextInitializerClasses这个方法 -->遍历返回的列表分别执行以下操作 -->resolveTypeArgument(解析ApplicationContextInitialize对应的范型的具体类型) -->initializerContextClass.isInstance(wac这里的参数是webApplicationContext) initializerContextClass.isInstance-->|如果没有对应的具体类型或者webApplicationContext没有对这个Initiallize进行继承或实现的话|直接抛ApplicationContextException initializerContextClass.isInstance-->|条件成立|实力化对应的initializer并加入到ContextLoader中的contextIntializers列表中 -->对ContextLoader中的contextInitializers进行排序 -->然后对这个列表中的initializer调用initialize方法进行初始化入参为webApplicationContext -->到此customizeContext方法执行完成(定制容器方法结束) -->webApplication.refresh(刷新容器) -->从这里开始进入到AbstractApplicationContext -->整个refresh过程是一个代码同步块synchronized包装的 -->AbstractApplicationContext.applicationStartup#start(实际上就是标记一下刷新步骤) -->prepareRefresh(刷新容器准备阶段) -->设置一些状态并打印一些日志信息 -->initPropertySources(web.context.support.StandardServletEnvironment#initPropertySources和前面的一样) -->getEnvironmentz#validateRequiredProperties(验证必要的属性都是可解析的) -->AbstractApplicationContext.earlyApplicationListeners{判断pre-refresh applicationListeners是否为空} AbstractApplicationContext.earlyApplicationListeners-->|为空|pre-refresh监听器为空则用AbstractApplicationContext.applicationListeners的内容覆盖-->AbstractApplicationContext.earlyApplicationEevents AbstractApplicationContext.earlyApplicationListeners-->|非空|AbstractApplicationContext.applicationListeners清空后用AbstratcApplicationContext.earlyApplicationListeners覆盖 -->AbstractApplicationContext.earlyApplicationEevents(创建earlyApplicationEevents容器LinkedHashSet) -->prepareRefresh结束 -->obtainFreshBeanFactory(通知子类刷新内部BeanFactory) -->refreshBeanFactory(进入到refreshBeanFactory内部看过程) -->org.springframework.context.support.AbstractRefreshableApplicationContext#refreshBeanFactory(刷新BeanFactory) -->如果已经存在的BeanFactory则清理掉-->创建DefaultListableBeanFactory(执行createBeanFactory方法) -->创建DefaultListableBeanFactory的对象实例并指定ParentBeanFactory -->给该BeanFactory设置序列化ID -->定制BeanFactory -->如果AbstractRefreshableApplicationContext中的allowBeanDefinitionOverriding属性不为空{ApplicationContext是否设置了allowBeanDefinitionOverriding属性} 如果AbstractRefreshableApplicationContext中的allowBeanDefinitionOverriding属性不为空-->|非空|标记BeanFactory为可以覆盖beanDefinition-->如果AbstractRefreshableApplicationContext中的allowCircularReferences属性不为空{ApplicationContext是否设置了allowCircularReferences属性} 如果AbstractRefreshableApplicationContext中的allowCircularReferences属性不为空-->|非空|标记BeanFactory为可以循环刷新-->将beanDefinition加载到BeanFactory中(org.springframework.context.support.AbstractRefreshableApplicationContext#loadBeanDefinitions 有多种实现#PropertiesbeanDefinitionReader XmlBeanDefinitionReader 有待研究实现细节) -->将这个BeanFactory赋值给AbstractRefreshApplicationContext的beanFactory属性 -->返回容器中的beanFactory -->prepareBeanFactory(配置这个beanFactory的信息) -->setBeanExpressionResolver(设置SpEl表达式解析器) -->addPropertyEditorRegistrar(添加属性解析器它的作用就是解析各种配置信息到需要的地方) -->addBeanPostProcessor(添加Bean初始化的后置处理器之ApplicationContextAwareProcessor) -->ignoreDependencyInterface#EnvironmentAware(忽略EnvironmentAware的实现 避免使用set进行依赖注入) -->ignoreDependencyInterface#EmbeddedValueResolverAware(忽略EmbeddedValueResolverAware的实现 避免使用set进行依赖注入) -->ignoreDependencyInterface#ResourceLoaderAware(忽略ResourceLoaderAware的实现 避免使用set进行依赖注入) -->ignoreDependencyInterface#ApplicationEventPublisherAware(忽略ApplicationEventPublisherAware的实现 避免使用set进行依赖注入) -->ignoreDependencyInterface#MessageSourceAware(忽略MessageSourceAware的实现 避免使用set进行依赖注入) -->ignoreDependencyInterface#ApplicationContextAware(忽略ApplicationContextAware的实现 避免使用set进行依赖注入) -->ignoreDependencyInterface#ApplicationStartupAware(忽略ApplicationStartupAware的实现 避免使用set进行依赖注入) -->解决自动注入将容器中的beanFactory注入到BeanFactory的实现类 -->解决自动注入将容器注入到ResourceLoader实现类 -->解决自动注入将容器注入到ApplicationEventPublisher的实现类 -->解决自动注入将容器注入到ApplicationContext的实现类 -->addBeanPostProcessor(添加Bean初始化的后置处理器之ApplicationListenerDetector) -->检测是否设置了org.graalvm.nativeimage.imagecode这个技术很牛逼但是不了解 -->向容器中添加environment对象 -->向容器中添加systemProperties对象 -->向容器中添加systemEnvironment对象 -->向容器中添加applicationStartup对象 -->prepareBeanFactory结束 -->执行模版方法postProcessBeanFactory(执行钩子方法对前面的步骤进行补充可以继续添加对象到容器或添加后置处理器) -->打印日志'spring.context.beans.post-process' -->org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(执行BeanFactory的后置处理器 这个方法很重待深入研究) -->registerBeanPostProcessors(注册Bean的后置处理) -->initMessageSource(初始化容器的initMessageSource国际化处理) -->initApplicationEventMulticaster(初始化容器的initApplicationEventMulticaster事件广播) -->onRefresh(容器的钩子方法) -->registerListeners(容器注册监听器和earlyApplicatonEvents关联) -->finishBeanFactoryInitialization(完成BeanFactory初始化) -->设置setConversionService转换服务 -->addEmbeddedValueResolver(如果没有BeanFactoryPostProcessor设置一个嵌入式的解析器) -->创建LoadTimeWeaverAware实例 -->setTempClassLoader(停止使用临时的classLoader进行加载) -->冻结beanFactory中对应的bean的原数据禁止修改 -->preInstantiateSingletons(实例化剩余的对象实例 lazy的除外) -->finishBeanFactoryInitialization结束-->finishRefresh(完成刷新) -->clearResourceCaches(清理资源缓存) -->initLifecycleProcessor(初始化生命周期处理器 待研究) -->initLifecycleProcessor#onRefresh(创建bean加入treeMap) -->publishEvent(广播一个ContextRefreshedEvent事件) -->LiveBeansView.registerApplicationContext(将liveBean托管给MBeanServer) -->最后层层返回将这个webApplicationContext注册到servletContext中

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

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

相关文章

【开源系列】CentOS7下Docker环境搭建开源堡垒机Apache Guacamole

Apache Guacamole 是一个无客户端远程桌面网关。它支持 VNC、RDP 和 SSH 等标准协议。不需要插件或客户端软件。借助 HTML5,一旦在服务器上安装了 Guacamole,只需使用 Web 浏览器即可访问桌面。 1.Guacamole的架构介绍 Guacamole不是一个独立的网络应用程序,而是由多个部分组…

ThreeJs-07操控物体实现家具编辑器

本章节实现效果,通过gui快速添加场景,家具,并且可以快速设置家具实现一个编辑器效果一.基础设置与物体添加列表 用之前做过的一个案例来改首先不要这个模型,然后换个背景颜色,并且添加一个网格辅助器1.1 添加场景 先往事件对象里面添加一个函数,到时候点击就会调用这个函…

数据集划分;参数超参数;交叉验证

在机器学习和深度学习中,将数据分为训练集(Training Set)、验证集(Validation Set)和测试集(Test Set)是常见的做法,每部分数据承担不同的任务: 一.基本概念 1.训练集(Training Set):训练集用于训练模型,即通过算法调整模型的参数以最小化损失函数(Loss Function…

爱米导航网(imi),您的互联网书签搭子

爱米导航(Imi)网是一个综合性的互联网资源聚合平台,它以其丰富的内容和便捷的服务受到了广大用户的喜爱。该网站收录了数千个不同类型的互联网工具网站,覆盖了AI工具、自媒体运营工具、产品经理工具以及UI设计师工具等多个领域,为用户提供了一个一站式的解决方案。 爱米导…

记录一次springboot启动流程不完整版

1.Sort ApplicationInitializer:2.sort Listener:3.getRunListener:4.eventPublishingRunListener.starting 发布启动中事件; 构建 ApplicationArguments 参数, 4.1prepareEnvement: [StubPropertySource {name=servletConfigInitParams}, StubPropertySource {name=servletC…

键盘连击软件解决方案

解决的问题 jjjjjjjjjjjjjjjj键盘连击了,windows系统中的“筛选键”功能就能短暂解决这个问题,可是筛选的时间太长无法在面板设置更短的时间,但可以使用软件解决。 方法一 系统 筛选键 win+i 打开设置 -> 搜索“筛选键” -> 打开筛选键开关 使用限制:重复键最低只能设…

【建议收藏】最新版IDEA2024.3及 AI Assistant 一键激活到2099

成功永久激活 一、支持的IDE和版本支持JB家族所有IDE激活 支持版本为2021.3~2024.1二、如何破解激活 第一步:激活工具下载 为了防止破解工具被删除,通过公众号回复“「永久激活」”获取下载最新工具(如过期,请记得提醒我哦) 关注公众号后台回复“「永久激活」”,获取最新…

《平衡树》读后感

第一框,世界属于fhq-treap 是什么? 你说的对,但是《fhq-treap》是由范浩强自主研发的一款全新树形数据结构。数据结构发生在一个被称作「二叉搜索树」的幻想世界,在这里,被人创造的节点将被授予「随机优先级」,导引期望 \(O(\log n)\) 之力。treap 将扮演一位名为「根据优…

虚拟机unraid系统安装

首先下载unraid文件https://unraid.net/getting-started windows系统使用vmware虚拟机 创建虚拟机过程中注意usb的不同协议 2.0 3.0 由于unraid系统只能识别fat32协议的文件系统,因此需要将u盘格式化 可以使用easeus 或者 傲梅 https://www.easeus.com/partition-manager/ htt…

基于.NET WinForm开发的一款硬件及协议通讯工具

前言 今天大姚给大家分享一款基于.NET WinForm开发的一款硬件及协议通讯工具:PLC-CommunTools。 项目介绍 PLC-CommunTools是一款基于.NET WinForm开发的一款硬件及协议通讯工具,包含各类厂商的PLC协议及基础的TCP、串口通讯、IO口通讯等协议通讯功能的实现整合,注意还有一部…

游戏过程

根据是否结束游戏的逻辑选择对掷骰子的过程用bool申明变量掷骰子 static bool RollDice (w,h,ref Player p1,ref Player p2,Map map) {InfoClear(h);Console.ForegroundColor=p1.type==E_PlayerType.Player?ConsoleColor.Cyan:ConsoleColor.Meganta;if(p1.isPause){p1.isPause…

6.Group组件

关于Group组件的简单介绍首先,Group组件本身并不是一个“布局”类的组件,它只是一个容器,没有提供调整内部组件展示位置的方法,也就是说,当我们将多个组件(比如button)放在group中时,他们(根据流式规则?)会全部挤在窗口的左上角,当然,如果我们没有设置组件的大小的话…