SpringBoot启动流程深度解析

写在前面:

       由于该系统是底层系统,以微服务形式对外暴露dubbo服务,所以本流程中SpringBoot不基于jetty或者tomcat等容器启动方式发布服务,而是以执行程序方式启动来发布(参考下图keepRunning方法)。

       本文以调试一个实际的SpringBoot启动程序为例,参考流程中主要类类图,来分析其启动逻辑和自动化配置原理。


总览:

       上图为SpringBoot启动结构图,我们发现启动流程主要分为三个部分,第一部分进行SpringApplication的初始化模块,配置一些基本的环境变量、资源、构造器、监听器,第二部分实现了应用具体的启动方案,包括启动流程的监听模块、加载配置环境模块、及核心的创建上下文环境模块,第三部分是自动化配置模块,该模块作为springboot自动配置核心,在后面的分析中会详细讨论。在下面的启动程序中我们会串联起结构中的主要功能。

启动:

      每个SpringBoot程序都有一个主入口,也就是main方法,main里面调用SpringApplication.run()启动整个spring-boot程序,该方法所在类需要使用@SpringBootApplication注解,以及@ImportResource注解(if need),@SpringBootApplication包括三个注解,功能如下:@EnableAutoConfiguration:SpringBoot根据应用所声明的依赖来对Spring框架进行自动配置

@SpringBootConfiguration(内部为@Configuration):被标注的类等于在spring的XML配置文件中(applicationContext.xml),装配所有bean事务,提供了一个spring的上下文环境

@ComponentScan:组件扫描,可自动发现和装配Bean,默认扫描SpringApplication的run方法里的Booter.class所在的包路径下文件,所以最好将该启动类放到根包路径下

SpringBoot启动类

首先进入run方法

run方法中去创建了一个SpringApplication实例,在该构造方法内,我们可以发现其调用了一个初始化的initialize方法

这里主要是为SpringApplication对象赋一些初值。构造函数执行完毕后,我们回到run方法

该方法中实现了如下几个关键步骤:

1.创建了应用的监听器SpringApplicationRunListeners并开始监听

2.加载SpringBoot配置环境(ConfigurableEnvironment),如果是通过web容器发布,会加载StandardEnvironment,其最终也是继承了ConfigurableEnvironment,类图如下

可以看出,*Environment最终都实现了PropertyResolver接口,我们平时通过environment对象获取配置文件中指定Key对应的value方法时,就是调用了propertyResolver接口的getProperty方法

3.配置环境(Environment)加入到监听器对象中(SpringApplicationRunListeners)

4.创建run方法的返回对象:ConfigurableApplicationContext(应用配置上下文),我们可以看一下创建方法:

方法会先获取显式设置的应用上下文(applicationContextClass),如果不存在,再加载默认的环境配置(通过是否是web environment判断),默认选择AnnotationConfigApplicationContext注解上下文(通过扫描所有注解类来加载bean),最后通过BeanUtils实例化上下文对象,并返回,ConfigurableApplicationContext类图如下:

主要看其继承的两个方向:

LifeCycle:生命周期类,定义了start启动、stop结束、isRunning是否运行中等生命周期空值方法

ApplicationContext:应用上下文类,其主要继承了beanFactory(bean的工厂类)

5.回到run方法内,prepareContext方法将listeners、environment、applicationArguments、banner等重要组件与上下文对象关联

6.接下来的refreshContext(context)方法(初始化方法如下)将是实现spring-boot-starter-*(mybatis、redis等)自动化配置的关键,包括spring.factories的加载,bean的实例化等核心工作。

refresh方法

配置结束后,Springboot做了一些基本的收尾工作,返回了应用环境上下文。回顾整体流程,Springboot的启动,主要创建了配置环境(environment)、事件监听(listeners)、应用上下文(applicationContext),并基于以上条件,在容器中开始实例化我们需要的Bean,至此,通过SpringBoot启动的程序已经构造完成,接下来我们来探讨自动化配置是如何实现。


自动化配置:

       之前的启动结构图中,我们注意到无论是应用初始化还是具体的执行过程,都调用了SpringBoot自动配置模块

SpringBoot自动配置模块

       该配置模块的主要使用到了SpringFactoriesLoader,即Spring工厂加载器,该对象提供了loadFactoryNames方法,入参为factoryClass和classLoader,即需要传入上图中的工厂类名称和对应的类加载器,方法会根据指定的classLoader,加载该类加器搜索路径下的指定文件,即spring.factories文件,传入的工厂类为接口,而文件中对应的类则是接口的实现类,或最终作为实现类,所以文件中一般为如下图这种一对多的类名集合,获取到这些实现类的类名后,loadFactoryNames方法返回类名集合,方法调用方得到这些集合后,再通过反射获取这些类的类对象、构造方法,最终生成实例

工厂接口与其若干实现类接口名称

下图有助于我们形象理解自动配置流程

SpringBoot自动化配置关键组件关系图 

      mybatis-spring-boot-starter、spring-boot-starter-web等组件的META-INF文件下均含有spring.factories文件,自动配置模块中,SpringFactoriesLoader收集到文件中的类全名并返回一个类全名的数组,返回的类全名通过反射被实例化,就形成了具体的工厂实例,工厂实例来生成组件具体需要的bean。

之前我们提到了EnableAutoConfiguration注解,其类图如下

可以发现其最终实现了ImportSelector(选择器)和BeanClassLoaderAware(bean类加载器中间件),重点关注一下AutoConfigurationImportSelector的selectImports方法

该方法在springboot启动流程——bean实例化前被执行,返回要实例化的类信息列表。我们知道,如果获取到类信息,spring自然可以通过类加载器将类加载到jvm中,现在我们已经通过spring-boot的starter依赖方式依赖了我们需要的组件,那么这些组建的类信息在select方法中也是可以被获取到的,不要急我们继续向下分析

该方法中的getCandidateConfigurations方法,通过方法注释了解到,其返回一个自动配置类的类名列表,方法调用了loadFactoryNames方法,查看该方法

在上面的代码可以看到自动配置器会跟根据传入的factoryClass.getName()到项目系统路径下所有的spring.factories文件中找到相应的key,从而加载里面的类。我们就选取这个mybatis-spring-boot-autoconfigure下的spring.factories文件

进入org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration中,主要看一下类头

发现@Spring的Configuration,俨然是一个通过注解标注的springBean,继续向下看,

@ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class})这个注解的意思是:当存在SqlSessionFactory.class, SqlSessionFactoryBean.class这两个类时才解析MybatisAutoConfiguration配置类,否则不解析这一个配置类,make sence,我们需要mybatis为我们返回会话对象,就必须有会话工厂相关类

@CondtionalOnBean(DataSource.class):只有处理已经被声明为bean的dataSource

@ConditionalOnMissingBean(MapperFactoryBean.class)这个注解的意思是如果容器中不存在name指定的bean则创建bean注入,否则不执行(该类源码较长,篇幅限制不全粘贴)

       以上配置可以保证sqlSessionFactory、sqlSessionTemplate、dataSource等mybatis所需的组件均可被自动配置,@Configuration注解已经提供了Spring的上下文环境,所以以上组件的配置方式与Spring启动时通过mybatis.xml文件进行配置起到一个效果。通过分析我们可以发现,只要一个基于SpringBoot项目的类路径下存在SqlSessionFactory.class, SqlSessionFactoryBean.class,并且容器中已经注册了dataSourceBean,就可以触发自动化配置,意思说我们只要在maven的项目中加入了mybatis所需要的若干依赖,就可以触发自动配置,但引入mybatis原生依赖的话,每集成一个功能都要去修改其自动化配置类,那就得不到开箱即用的效果了。所以Spring-boot为我们提供了统一的starter可以直接配置好相关的类,触发自动配置所需的依赖(mybatis)如下:

这里是截取的mybatis-spring-boot-starter的源码中pom.xml文件中所有依赖:

因为maven依赖的传递性,我们只要依赖starter就可以依赖到所有需要自动配置的类,实现开箱即用的功能。也体现出Springboot简化了Spring框架带来的大量XML配置以及复杂的依赖管理,让开发人员可以更加关注业务逻辑的开发。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【做一名健康的CSDNer】

程序员由于工作性质,常常需要长时间面对电脑,这可能对身心健康带来挑战。以下是一些实用的建议,帮助程序员保持身心健康: 规律生活:建立健康的生活习惯,包括规律的作息时间和固定的饮食时间,保证…

书生·浦语大模型实战营Day04OpenXLab 部署

书生浦语大模型实战营Day04OpenXLab 部署 如何在 OpenXLab 部署一个 InternLM2-7B chat 的应用。 OpenXLab浦源平台介绍 OpenXLab 浦源平台以开源为核心,旨在构建开源开放的人工智能生态,促进学术成果的开放共享。OpenXLab面向 AI 研究员和开发者提供…

【python】使用python和selenium实现某平台自动化上传作品的全步骤

第一,我们需要下载python并安装 下载地址:https://www.python.org/downloads/release/python-3123/ 3.x版本的python自带pip工具,因此不需要额外下载。 ModuleNotFoundError: No module named seleniumpip用于下载python适用的各类模块&…

yolov8自带的P2层如何开启

YOLOv8模型 简述YOLOv8不同size模型简述 在最开始的YOLOv8提供的不同size的版本,包括n、s、m、l、x(模型规模依次增大,通过depth, width, max_channels控制大小),这些都是通过P3、P4和P5提取图片特征; 正…

网络编程 -- 简易TCP网络程序

一 字符串回响 1.1 核心功能 字符串回响程序类似于 echo 指令,客户端向服务器发送消息,服务器在收到消息后会将消息发送给客户端,该程序实现起来比较简单,同时能很好的体现 socket 套接字编程的流程。 1.2 程序结构 这个程序我们…

Python编程玩转二维码

文章目录 Python编程玩转二维码第一部分:背景介绍第二部分:qrcode库是什么?第三部分:如何安装这个库?第四部分:库函数使用方法第五部分:场景应用第六部分:常见Bug及解决方案第七部分…

动力学重构/微分方程参数拟合 - 基于模型

这一篇文章,主要是给非线性动力学,对微分方程模型参数拟合感兴趣的朋友写的。笼统的来说,这与混沌系统的预测有关;传统的机器学习的模式识别虽然也会谈论预测结果,但他们一般不会涉及连续的预测。这里我们考虑的是&…

Git ignore、exclude for TortoiseGit 小结

1.Ignore Type:忽略类型,也即忽略规则,如何去忽略文件? 1.1.Ignore item(s) only in containing folder(s):仅忽略在包含在文件夹中项目。 仅忽略该文件夹下选定的patterns。the patterns其实就是文件类型,比如.txt后…

文本美学:text-image打造视觉吸引力

当我最近浏览 GitHub 时,偶然发现了一个项目,它能够将文字、图片和视频转化为文本,我觉得非常有趣。于是我就花了一些时间了解了一下,发现它的使用也非常简单方便。今天我打算和家人们分享这个发现。 项目介绍 话不多说&#xf…

面试(05)————Redis篇

目录 一、项目中哪些地方使用了redis 问题一:发生了缓存穿透该怎么解决? 方案一:缓存空数据 方案二:布隆过滤器 模拟面试 问题二: 发生了缓存击穿该怎么解决? 方案一:互斥锁 方案二&#xff…

【GPTs分享】GPTs分享之Image Recreate | img2img​

简介 该GPT是一个专门用于图像编辑、重建和合并的工具。它通过详细的自动图像描述和生成,帮助用户从源图像中重现或修改图像。此工具设计用于为视障用户提供图像内容的详细描述,并生成全新的图像,以满足特定的视觉需求。 主要功能 \1. 图像…

Clion 2023.1.5 最新详细破解安装教程

CLion 最大的优点是跨平台,在Linux、Mac、Windows 上都可以运行。CLion 还同时支持 GCC、Clang、MSVC 这 3 种编译器,使用 CLion 编写程序,程序员可以根据需要随意切换使用的编译器。 第一步: 下载最新的 Clion 2023.1.5 版本安装包 我们先…

掌握字幕艺术:pysrt 库指南

文章目录 掌握字幕艺术:pysrt 库指南第一部分:背景介绍第二部分:库是什么?第三部分:如何安装这个库?第四部分:库函数使用方法第五部分:场景应用第六部分:常见Bug及解决方…

Hive基础3

一、表的分区 大数据开发数据量较大,在进行数据查询计算时,需要对数据进行拆分,提升的查询速度 1-1 单个分区 单个分区是创建单个目录 -- 创建表指定分区,对原始数据进行分区保存 create table new_tb_user(id int,name string,ag…

Linux嵌入式驱动开发-linux中断

文章目录 linux中断原理中断控制器GIC中断源分类 中断ID、中断线(中断号/中断源)中断ID中断线(中断号/中断源)MX6U中断源 上半部与下半部(顶半部和底半部)下半部实现机制linux软中断注册软中断触发软中断初始化软中断 taskletasklet_init:初始…

【AIGC】文本与音频生成引领行业革新

AIGC技术崛起 一、AIGC技术概述二、文本生成:结构化与创作型并进三、实例与代码解析四、音频生成:语音合成技术大放异彩五、结语 在科技的浪潮中,人工智能与大数据的结合不断推动着时代的进步。其中,AIGC(Artificial I…

安居水站:水站经营秘籍:年入30万不是梦。水站创业指南。

在这个快节奏的社会里,初创企业家们总是在寻找一条明路,以在竞争激烈的市场中立足。为了帮助他们更好地实现这一目标,我根据经验决定制定一份水站经营指导手册。这份手册将详细阐述如何从零起步,如何运营,如何进行市场…

智慧浪潮下的产业园区:解读智慧化转型如何打造高效、绿色、安全的新产业高地

随着信息技术的飞速发展,智慧化转型已经成为产业园区发展的重要趋势。在智慧浪潮的推动下,产业园区通过集成应用物联网、大数据、云计算、人工智能等先进技术手段,实现园区的智慧化、高效化、绿色化和安全化,从而打造成为新产业高…

x-cmd ai | x openai - 用于发送 openai API 请求,以及与 ChatGPT 对话

介绍 Openai 模块是 Openai 大模型 Chatgpt 3 和 ChatGPT 4 命令行实现。x-cmd 提供了多个不同平台间多种 AI 大模型的调用能力。无论是本地模型还是 Web 服务上的模型,用户都可以在不同的 AI 大模型间直接无缝切换,并能把之前的聊天记录发送给新的大模…

【PCL】教程conditional_euclidean_clustering 对输入的点云数据进行条件欧式聚类分析...

[done, 3349.09 ms : 19553780 points] Available dimensions: x y z intensity 源点云 Statues_4.pcd 不同条件函数output.pcd 【按5切换到强度通道可视化】 终端输出: Loading... >> Done: 1200.46 ms, 19553780 points Downsampling... >> Done: 411…