欢迎光临散文网 会员登陆 & 注册

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

2021-03-31 15:55 作者:动力节点小王本王  | 我要投稿



本篇文章主要内容

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的核心组件类;

ConfigurationClassPostProcessorAutowiredAnnotationBeanPostProcessor等;

4、调用refreshContext() 方法启动Spring容器(12步)和内置的Servlet容器;

如果想更深入的学习springboot,奉上springboot全套视频教程,视频学习效果更佳,走过路过别忘素质三连哦~~


详细SpringBoot框架教程——SpringBoot源码分析的评论 (共 条)

分享到微博请遵守国家法律