详细SpringBoot框架教程——SpringBoot源码分析

本篇文章主要内容
SpringBoot源码构建
验证SpringBoot源码环境是否正常
阅读源码指导原则
SpringBoot启动流程源码分析
视频观看戳👇👇👇

SpringBoot源码构建
1、安装和配置好JDK环境环境变量(JDK8+);
2、安装和配置好Gradle;官网:https://gradle.org
安装gradle(需要先安装JDK),Gradle直接解压到一个目录即完成安装;
Gradle配置环境变量,配置GRADLE_HOME 和Path;
使用gradle -v 验证Gradle环境是否正常;
Springboot源码从2.3.1版本开始由Maven改为了Gradle;
3、当前我使用的是IDEA 2020.1.3 旗舰版
File -->Setting-->Editor-->File Encodings -->全部改为UTF-8
安装代码统计插件:Statistic
安装英文翻译插件:ECTranslation
4、下载SpringBoot源码:https://github.com/spring-projects/spring-boot
5、解压下载下来的最新SpringBoot源码:spring-boot-2.3.1.RELEASE.zip
6、进入解压后的目录,比如:D:\project\opensource\spring-boot-2.3.1.RELEASE
7、阅读解压后的源码目录下的README.adoc文件,里面告诉了我们如何构建源码;
8、进入源码目录的dos窗口,执行:gradlew publishToMavenLocal
修改默认下载gradle文件路径
distributionUrl=file:///C:/Users/Administrator/.gradle/wrapper/gradle-6.4-bin.zip

执行的时候,可能会遇到错误,主要是因为一些插件从gradle网站下载失败导致的,此时需要翻墙软件(科学上网),才能下载成功;

出现上面的 git 的错误,是因为springboot源码构建需要保证源码是处于一个git仓库中,所以我们把源码纳入本地仓库管理中,依次执行如下命令:
创建.git目录: git init
将springboot源码目录加入暂存区: git add *
提交springboot源码提交到本地Git仓库: git commit -m 'springboot'

出现error: open:(.....) Filename too long错误,是因为路径太长了,默认是260个字符,解决方法:
git config core.longpaths true
接下来再进行构建:gradlew publishToMavenLocal

然后导入idea,等待加载完成,如果是第一次导入,需要下载一个依赖及插件,可能需要等待一段时间,会慢一些,如果某些插件下载失败,也会报错,通过启动翻墙软件(科学上网),这样保证从国外一些网站下载依赖和插件没有问题,然后构建成功;

显示成功,接下来就可以开始在源码的基础上创建一个测试项目,进行源码的阅读;
如果遇到源码发乳Idea中报一个format的格式错误的话,请dos窗口下执行:
gradlew -p buildSrc format
验证SpringBoot源码环境是否正常
创建一个spring-boot-zweb模块,编写springboot代码并运行,验证springboot源码环境构建是否正常;
加入springboot的依赖,根据需要添加依赖,举例如下:

最后运行spring-boot-zweb的main方法测试一下springboot环境是否正常?
一般情况下,第一次运行会比较慢,后面的运行会变快;
阅读源码指导原则
1、寻找入口
2、断点跟踪
3、先粗后细
4、精略结合
5、猜想验证
我们有了前面大量的源码阅读经验,相信大家对源码阅读并不感到陌生;
SpringBoot启动流程源码分析
SpringBoot启动流程(SpringBoot启动原理)
启动流程主要分为三个部分:
第一部分进行SpringApplication的初始化模块,配置一些基本的环境变量、资源、构造器、监听器;(了解一下)
第二部分实现了应用具体的启动方案,包括启动流程的监听模块、加载配置环境模块、及核心的创建Spring上下文环境模块;(掌握)
第三部分是自动化配置模块,该模块是SpringBoot自动配置的核心;(掌握)
宏观步骤:(概括为18个小步骤)
https://www.processon.com/view/link/5dc15b71e4b0335f1e4eb6fe
1、创建并启动计时监控类StopWatch
2、初始化应用上下文和异常报告集合(ConfigurableApplicationContext和Collection<SpringBootExceptionReporter>)
3、设置系统属性 configureHeadlessProperty()
4、创建Spring运行的监听器并启动
5、初始化默认应用参数类
6、准备Spring环境
7、创建beanner打印类
8、创建应用Spring上下文(也就是spring容器)
9、准备异常报告器
10、准备应用上下文(也就是spring容器)
11、刷新上下文(也就是spring容器)
12、应用上下文刷新后置处理(也就是spring容器)
13、停止计时监控类
14、输出日志信息
15、发布应用上下文启动完成事件
16、执行所有Runner运行器(如果实现CommandLineRunner接口)
17、发布应用上下文就绪事件
18、完成返回容器对象
SpringBoot启动流程源码分析
1、入口main方法执行;

2、执行run方法;

3、看一下run(new Class<?>[] { primarySource }, args);方法;

//这个run方法主要做两件事情:
//1、new了一个SpringApplication 这么一个对象;
(1) 把main方法这个类赋给一个成员变量;
(2) 判断是java项目还是web项目;
(3) 设置了一个初始化器和事件发送的监听器;
//2、然后执行SpringApplication对象的run()方法;
4、先看做的第一件事情,new了一个SpringApplication对象

这里面用到了一种类似于Java SPI机制的方式扫描META-INF/spring.factories这个文件,并且加载 ApplicationContextInitializer、ApplicationListener 接口实例;
(1)ApplicationContextInitializer 这个类当springboot上下文Context初始化完成后会调用;
(2)ApplicationListener 当springboot启动时事件change后都会触发
我们可以自定义实现ApplicationContextInitializer、ApplicationListener 接口,然后运行时会被触发执行;
5、然后我们看做的第二件事情,执行new出来的SpringApplication对象的run()方法;



6、接下来我们重点看一下run方法里面的几个重要步骤,首先看看红色标记的创建spring容器上下文context = createApplicationContext();这段代码主要是根据项目类型创建Spring上下文,并且会注入几个核心组件类;

Web类型项目创建上下文对象 AnnotationConfigServletWebServerApplicationContext,这里会把 ConfigurationClassPostProcessor 、
AutowiredAnnotationBeanPostProcessor 等一些核心组件加入到Spring容器,这其实已经是spring ioc容器的源码,如果了解spring ioc源码,那么对springboot源码的阅读会有很大的帮助;
7、然后再看一下run方法里面另一个比较重要的步骤,红色标记的创建和刷新spring容器refreshContext()方法,
refreshContext(context) 这个方法,该方法启动spring的代码加载了bean,还启动了内嵌的web容器;

接下来进入到Spring ioc容器刷新和创建的12个步骤的源码中,AbstractApplicationContext - >refresh()方法,在这12个步骤中,这里主要看一下onRefresh() 这个方法,但是发现这个方法里面什么都没有,显然是一个钩子方法,它会钩到它子类重写onRefresh()方法,所以去看子类里面的onRefresh()方法;
由于我们这里是一个Web项目,所以就可以看到 ServletWebServerApplicationContext 这个类,这个类下面的 onRefresh() 方法:

继续看下getWebServletFactory() 这个方法,这里面选择出哪种类型的web容器

再回头去看factory.getWebServer(getSelfInitializer()) ,转到定义就会看到很熟悉的名字tomcat

内置的Servlet容器就是在onRefresh() 方法里面启动的,至此一个Servlet容器就启动OK了;
总结:
1、new了一个SpringApplication对象,使用一种类似于SPI机制的技术加载ApplicationContextInitializer、ApplicationListener 接口实例;(非重点)
2、调用SpringApplication.run() 方法,run方法里面大概有18个小步骤;
3、调用createApplicationContext()方法创建Spring IOC上下文对象,创建上下文对象同时会注册spring的核心组件类;
ConfigurationClassPostProcessor、AutowiredAnnotationBeanPostProcessor等;
4、调用refreshContext() 方法启动Spring容器(12步)和内置的Servlet容器;
如果想更深入的学习springboot,奉上springboot全套视频教程,视频学习效果更佳,走过路过别忘素质三连哦~~

