首页 > 其他分享 >【学习笔记】(二)SpringBoot项目启动的大致流程

【学习笔记】(二)SpringBoot项目启动的大致流程

时间:2024-11-28 22:33:46浏览次数:10  
标签:容器 SpringBoot 初始化 对象 创建 流程 笔记 bean 处理器

SpringBoot执行流程梳理

书接上回,上回说到JarLaunch通过反射调用,进入到了我们的Spring项目main方法中。本节将会大致的梳理Spring启动的执行流程,并把我在阅读源码时碰到的问题做一个简要的记录。为后续引出我们常常叨叨的Spring自动配置打下基础。


文章目录


关键流程

在这里插入图片描述

老天爷视角

我把SpringBoot项目启动的流程按顺序主要分为了7块内容:
1、SpringApplication对象创建
2、项目启动的前置处理
3、环境变量包装
4、banner打印
5、容器创建和初始化
6、容器内容填充
7、项目启动的后置处理
接下来我将对这7块内容及其大致流程以及涉及到的一些作用做一个大致的介绍

一、SpringApplication对象创建

在这里插入图片描述

对象的创建对于我们的web项目来说,比较重要的内容:
1、红框里的设置应用类型,这关乎后面环境变量对象创建、容器创建的类型选择;
2、其次是黄框里的引导初始化器、容器初始化器以及监听器,他们会在后续的run方法中被调用;
我觉得这里比较有意思,也有必要一说的就是这些初始化器、监听事件以及后续的各种后处理器的加载。他们都是通过加载META-INF/spring.factories文件,拿到对应的配置,然后通过反射获取到的对象,进而把他们加载到容器或相应对象当中的。
在这里插入图片描述
上图红框中的application就是我们创建的application对象,for循环里拿到的listener就是我们黄框里addListeners()添加的监听器。可以看到,当后续的run方法中的各种事件进行发布时,他就会被调用。

3、最后就是主类推断,目前我个人理解它的主要作用就是用于banner打印时把启动类打出来(此处我的理解大概率有误,如有请指出)。

二、项目的启动前置处理

接下来我们就进入到run方法里看看初始化在做的事情。

1.创建引导容器

在这里插入图片描述
图1-1

首先是createBootstrapContext(),他的作用其实是呼应的application对象创建时的加载初始化器。他会在方法里for循环地调用初始化方法,并将引导容器返回。说起这个引导容器的作用,我的理解是我们的一些自定义拓展数据需要有一个集中存放的地方,而这个地方就是引导容器,他会把我们的数据一致缓存到容器对象创建完成,然后触发关闭事件。
在这里插入图片描述

2.创建事件监听器对象

在这里插入图片描述

再然后就是创建spring应用的事件监听器对象,该对象会在后续的各种事件发布时调用。
application对象创建时加载的监听器,跟这里的对象之间是存在关系的。当后者的监听事件被出发了,他会通过EventPublishingRunListener通过application对象获取到并调用。我个人是这样理解的:前者是被加载进来的具体事件,后者是一个对象,在被调用时,可以触发前者里面的具体操作,后续我会通过一个例子做简单的介绍。其实我一开始看源码的时候都蒙了。

三、环境变量包装

在这里插入图片描述
首先会将我们通过java -jar启动时传递的参数作为args,包装成一个应用变量对象,该对象在环境变量包装以及后续的项目启动后处理阶段会在一个runner接口中被用到。需要提一嘴的是,这个args是作为优先级最高的环境变量而存在的,这也同步解释了java -jar 敲的参数为什么能起作用,而且能覆盖内部配置文件所设置的信息的原因。
然后就进入我们获取环境变量的方法里。
在这里插入图片描述
在这个方法中主要做的事情只有一个:将我们的系统环境变量、系统属性、yml配置文件等信息,通过KV的方式进行收集和包装,然后封装到一个环境变量对象当中返回,而这个对象是根据早期确定好的容器类型进行创建。
他的主要流程:
1、创建环境对象
2、将args添加进环境对象中
3、通过attach()方法对配置文件的key进行统一化,方便后续取值
4、触发environmentPrepared事件,在这个事件里,会执行一个环境后处理器,取做一些环境变量信息的增强,例如让yml等配置文件得以被读取。有意思的是,这个触发后处理器的事件本身,就是在application对象创建时获取到的。稍微填一下创建对象时我挖的坑,红框里的key就对应着application对象创建时,setListeners()方法里加载的监听器事件。大家可以比对一下相应的代码。

后处理器对应的key 在这里插入图片描述
下方的红框跟上方的key是对应的在这里插入图片描述

5、通过bindToSpringApplication()将我们在配置文件中设置的“spring.main”打头的key中的值,赋值到我们的application对象对应成员变量当中

四、banner打印

光看名字,其实我当时是一脸懵的,但是我把下面的图放出来可能就恍然大悟了
在这里插入图片描述
我的理解,他主要就是把图标打印了出来,假如我们想打印自己的,那就重写他的方法就好,下面是他的具体代码
在这里插入图片描述

五、容器创建和初始化

1、容器创建

该方法主要是调用createApplicationContext()方法,根据容器类型判断需要new出来的对象类型,然后返回
在这里插入图片描述

2、容器初始化

在这里插入图片描述

这个阶段主要的任务:
1、将前期创建的环境对象绑定到创建的容器中
2、调用创建application对象时加载的容器初始化器的初始化方法
3、发布容器就绪事件
4、发布引导容器关闭事件
5、添加一系列的后处理器(重点),并对一些额外添加进来的资源,按照来源顺序(Clazz、XML文件、包、CharSequence)先行加载bean定义
在这里插入图片描述
关键就是这个方法里创建的对象。一直沿着下面红框的对象进来
在这里插入图片描述

就会看到下图的这三个bean / bean工厂后处理器。这三个后处理器是自动配置和自动装配的关键
在这里插入图片描述

6、发布容器加载完成事件

六、容器内容填充

这个方法就是整个spring框架的关键。前面所有的对象创建、后处理器加载都是为了这一步的执行。
这一步做的事情主要是:
1、通过prepareRefresh()对环境变量中的参数进行必要性校验,若缺少必要的参数就报错
2、通过prepareBeanFactory(),给bean工厂增加一些额外配置:

  1. 对一些aware接口的自动装配行为进行忽略(这是个人理解,不一定对)
  2. 对个别接口实现类对应的bean进行指定(用于避免接口多实现时不知道应该添加那个bean到容器里的问题)
  3. 添加基础的bean后处理器,如后续会用到的ApplicationListenerDetector,它将在bean初始化后,通过对每个bean进行后处理,主要目的是判断当前bean是否是ApplicationListener的实现类对象,是就添加进事件监听器集合中,供后续的registerListeners()使用。
  4. 将例如环境对象等基础对象直接加入到bean容器当中

3、执行我们期待已久的bean工厂后处理器,在这里面将会对容器初始化时加载的后处理器,然后通过加载的bean工厂后处理器,将更多的自定义后处理器加载进来,最终共同将项目中所有标记为需要被容器管理的bean的bean定义收集好并保存到beanDefinitionMap中。
在这里插入图片描述
接下来就是按实现了PriorityOrdered接口、Ordered接口以及其他,作为后处理器的执行顺序,进行自定义后处理器的执行。
在这里插入图片描述

4、添加spring框架自带的bean后处理器,并根据执行bean工厂后处理器阶段获取的bean定义,通过getBean()获取所有bean后处理器对象,并加载到容器当中。
在这里插入图片描述
5、通过initMessageSource()做一些类似国际化之类的处理。
6、初始化事件广播器。针对这个广播器跟前面的事件发布器区别的理解,我个人是这么看的,前者是我丢一个广播事件进来,然后谁要执行什么操作,我不关注;后者是我固定了几个动作,当我触发了特定动作后(比如环境就绪事件),所有实现了这个动作的监听器就都来执行。当然,从代码的逻辑来看,他们最后都是要到SimpleApplicationEventMulticaster#multicastEvent中进行事件处理和广播。
7、执行onRefresh()创建我们配置的web服务器,一般是默认的tomcat,假如不在配置文件中自定义连接数等配置项,将加载默认的配置。完成一系列的服务器初始化后,将调用start方法启动服务器。(看这块逻辑,一开始我被接口里的空方法给坑的一愣一愣的囧)
8、registerListeners()将2.3步ApplicationListenerDetector的后处理方法执行结果(即项目中的各种监听器bean),加入到刚才初始化完成的事件广播器当中。
9、通过大名鼎鼎的finishBeanFactoryInitialization(),对bean工厂后处理器处理完的bean定义,进行单例bean的实例化操作,即反射创建对象或创建代理对象。在此期间还会基于各种aware接口、bean后处理器,对bean对象进行增强和操作,希望下下篇能记录下我对这块的学习笔记。
在这里插入图片描述
拿到bean定义后就开始循环获取bean
在这里插入图片描述
最后在对实现了SmartInitializingSingleton接口的bean进行后置处理
在这里插入图片描述

10、刷新容器。主要的功能其实是初始化生命周期处理器,然后对实现了生命周期处理接口的bean进行start方法的循环执行。最后,借助第6步初始化的广播器,发布容器刷新完成事件。

七、项目启动的后置处理

对于这个阶段,我个人其实就是把他定性为给开发人员更多的拓展点去增强我们的项目内容。例如发布started事件、调用Runner接口的实现类进行相关拓展。
最后的最后,发布就绪事件。至此整的spring项目主要的启动流程就基本结束了。

标签:容器,SpringBoot,初始化,对象,创建,流程,笔记,bean,处理器
From: https://blog.csdn.net/Riven_mikasa/article/details/143998414

相关文章

  • 基于springboot的智能公交系统
      博主介绍:java高级开发,从事互联网行业六年,熟悉各种主流语言,精通java、python、php、爬虫、web开发,已经做了多年的设计程序开发,开发过上千套设计程序,没有什么华丽的语言,只有实实在在的写点程序。......
  • 英文论文阅读笔记3
    2.Theimpactofreputation-basedheterogeneousevaluationandlearningoncooperationinspatialpublicgoodsgame基于声誉的异质性评估和学习在空间公共物品博弈合作上的影响​本论文整体上的工作量还有创新点我认为是我目前看过的论文之最(当然,我现在并不确......
  • 2024/11月 读书笔记 - 4《构建之法》--- 第四章
    第四章深入探讨了软件开发中的结对合作模式。前三节:代码规范本章节的前三节聚焦于代码规范,包括风格规范和设计规范等,为结对合作提供了共同遵循的标准。第四节:代码复审第四节讨论了代码复审的重要性,强调复审的核心在于确认代码是否在既定规范内有效解决问题。第五节:结对编程......
  • 2024/11月 读书笔记 - 5《构建之法》--- 第五章
    第五章深入探讨了团队合作的重要性及其运作流程。第一节:团队与非团队的区别本节阐述了团队与非团队之间的差异。团队成员围绕共同目标协作,即使他们不必同时工作,也能通过分工和相互依赖来完成任务。第二节:软件团队的运作模式本节介绍了多种软件团队的运作模式:主治医师模式:首席......
  • 【笔记总结】华为云:应用上云后的安全规划及设计
    一、背景和问题        数字化时代,随着信息技术的飞速发展,企业和各类组织纷纷将自身的应用程序迁移至云端。云计算凭借其诸多优势,如成本效益、可扩展性、灵活性以及便捷的资源共享等,已然成为了现代业务运营的重要支撑。    今年,我所在企业也将IT系统全面迁移......
  • [笔记]Important Tricks And Lemmas
    图论对于图路径的构造,常常思考是否可以对叶子节点进行某种配对。按照dfs序对节点进行配对是考虑的方向之一。例题P7320「PMOI-4」可怜的团主,P4665[BalticOI2015]。树上路径的交是路径。路径满足边数等于点数\(-1\),通常可以做某些神秘容斥。例题:2024省选集训Day8B......
  • [笔记]杜教筛 & Powerful Number 筛
    杜教筛杜教筛的作用杜教筛可以快速求出积性函数前缀和。如\(\varphi\),\(\mu\)等。什么是杜教筛定义\(f(x)\)为一个积性函数,求\(F(x)=\sum\limits_{i=1}^{n}f(x)\)。考虑构造函数\(h,g\),使得\(h=f*g\),即\(h(n)=\sum\limits_{d|n}f(d)g(\dfrac{n}{d}......
  • [笔记]动态规划优化(斜率优化,决策单调性优化)
    本文主要记录某些动态规划思路及动态规划优化。首先先把以前写过的斜率优化祭出来。斜率优化\(\text{P5017[NOIP2018普及组]摆渡车}\)经典例题。设\(f_i\)表示最后班车在\(i\)时刻发车,所有人等待时间和的最小值。(这里的所有人是指到达时刻小于等于\(i\)的所有人)。......
  • 基于Java+SpringBoot+Mysql实现的点卡各种卡寄售平台功能设计与实现一
    一、前言介绍:1.1项目摘要随着电子商务和在线支付技术的快速发展,数字商品和虚拟货币的交易需求日益增长。点卡及各种卡类商品(如游戏点卡、话费充值卡、礼品卡等)作为数字商品的一种,因其便捷性和即时性,在市场中占据了重要地位。然而,传统的点卡销售方式往往存在渠道单一、交易效率......
  • [笔记]行列式
    本文部分内容来自《高等代数》。行列式定义对于一个\(n\)阶行列式\[A_{n\timesn}=\begin{vmatrix}a_{11}&a_{12}&\cdots&a_{1n}\\a_{21}&a_{22}&\cdots&a_{2n}\\\vdots&\vdots&\ddots&\vdots\\a_......