我们上3个篇章写了springboot的自动装配、servlet组件的注入以及web容器实现内嵌的原理,现在我们来看springboot启动过程中到底做了些什么,也就是打开我们的run方法:

这里我们可以看到我们的run方法会new出一个springboot自己的一个容器,然后执行里面的run方法,这个args参数就是我们运行项目时所带的参数;因为这里new了一个springboot容器,所以我们打开SpringApplication,看里面初始化了什么东西:

可以看到,其实springboot容器里并没有做什么事,无非是做些判断,这些判断大多是通过判断容器里是否有某个类从而进行确定,比如判断是web应用里面检查的就是容器里是否有servlet类,是否加载了spring-web这个spring源码项目;而这里的初始化文件我们可以打开:

这两个初始化大类大致上的作用是初始化监听器,下面的这个类是全局的一个监听器,通过观察者的一个设计模式,我们可以发布各种各样的事件,然后进行监听,这里就不做过长的讲解(毕竟到现在我们的run方法还没讲==!),有兴趣的可以打开这些初始化类并学习spring里的监听器内容;

最后的这个找配置类其实就是通过拿到异常方法的调用栈,找到是否有main方法,再通过main方法返回你的主配置类名:

至此,我们应该大致知道在run方法运行前springboot做了哪些操作,接下来打开springboot容器里的这个run方法:

这里挑选我觉得比较实用的内容来讲:

首先是这个从配置文件读取的SpringApplicationRunListener接口的实现类,

这里我们自定义一个MyRunListener继承这个接口,重写接口原本的方法starting、started、running等等的方法即可让容器在启动前做一些自定义的操作,注意要把这个类写进

这个配置文件中;

其实在准备初始化阶段springboot做的就是发布监听;

我们打开refreshContext(context);看看在spring容器的初始化方面springboot做了哪些改进:

可以看到这里调用的super.refresh其实就是spring里本身的refresh()极度不要脸的照搬过来哈,我们再看里面的onRefresh方法

因为这个方法是spring容器在初始化后提供我们可以对容器做出修改的方法

可以看到,springboot在初始化时做的唯一改变就是添加了对web容器的判断,看其是否内嵌:

这里就很好地结合了之前讲的内嵌web容器以及注入servlet组件的原理了;先看一下web容器,如果是外部容器,即war包启动,通过web容器带动IOC启动,想想之前的java Config技术,其实就是利用WebApplicationInitializer这个接口,实现这个接口的类在tomcat运行时会调用里面的onStartup方法,我们重写这个onStartup方法,在里面创建web应用上下文,并加入监听器,在初始化context的时候会运行run方法,即启动IOC容器,所以判断项目是jar包启动还是war包启动,如果没拿到servletcontext,那就是以jar包启动:

看这里的getSelfInitializer(),初始化的正好对应开启的就是我们之前将servlet组件注入的里的onStartup方法,我们从spring容器里拿到所有实现了SevletContextInitializer的bean,再运行onStartup方法,把这些组件加入到servletcontext中,最后再通过getWebServer方法启动和获取web容器;也就是内嵌web容器和外部容器正好相反,内嵌的web容器是通过IOC来启动web容器,而外部容器是通过web容器来启动IOC;

至此,springboot在初始化Spring容器所作的贡献已然结束,我们再回到run方法里,可以看到后面无非就是打印一些日志输出以及一些容器启动后的监听器监听事件,所有简单总结下run方法里的作用:一、初始化springboot容器(1、判断上下文环境;2、加载Spring.factories配置文件里的ApplicationContextInitializer和ApplicationListener;3、找到main方法所在类);二、启动Sring容器(发布各式各样的监听器监听、重写Spring里的onReference方法:判断是否启动内嵌tomcat)

最后,再附上一张在网上找的Springboot的启动流程图:

springboot源码(4)的更多相关文章

  1. springboot源码解读

    springboot源码从main函数开始 public static void main(String[] args) { ApplicationContext app = SpringApplic ...

  2. SpringBoot源码分析之SpringBoot的启动过程

    SpringBoot源码分析之SpringBoot的启动过程 发表于 2017-04-30   |   分类于 springboot  |   0 Comments  |   阅读次数 SpringB ...

  3. SpringBoot源码篇:深度分析SpringBoot如何省去web.xml

    一.前言 从本博文开始,正式开启Spring及SpringBoot源码分析之旅.这可能是一个漫长的过程,因为本人之前阅读源码都是很片面的,对Spring源码没有一个系统的认识.从本文开始我会持续更新, ...

  4. Springboot源码分析之项目结构

    Springboot源码分析之项目结构 摘要: 无论是从IDEA还是其他的SDS开发工具亦或是https://start.spring.io/ 进行解压,我们都会得到同样的一个pom.xml文件 4. ...

  5. SpringBoot源码学习系列之异常处理自动配置

    SpringBoot源码学习系列之异常处理自动配置 1.源码学习 先给个SpringBoot中的异常例子,假如访问一个错误链接,让其返回404页面 在浏览器访问: 而在其它的客户端软件,比如postm ...

  6. SpringBoot源码学习系列之嵌入式Servlet容器

    目录 1.博客前言简单介绍 2.定制servlet容器 3.变换servlet容器 4.servlet容器启动原理 SpringBoot源码学习系列之嵌入式Servlet容器启动原理 @ 1.博客前言 ...

  7. 【spring-boot 源码解析】spring-boot 依赖管理梳理图

    在文章 [spring-boot 源码解析]spring-boot 依赖管理 中,我梳理了 spring-boot-build.spring-boot-parent.spring-boot-depen ...

  8. SpringBoot源码解析系列文章汇总

    相信我,你会收藏这篇文章的 本篇文章是这段时间撸出来的SpringBoot源码解析系列文章的汇总,当你使用SpringBoot不仅仅满足于基本使用时.或者出去面试被面试官虐了时.或者说想要深入了解一下 ...

  9. 外部配置属性值是如何被绑定到XxxProperties类属性上的?--SpringBoot源码(五)

    注:该源码分析对应SpringBoot版本为2.1.0.RELEASE 1 前言 本篇接 SpringBoot是如何实现自动配置的?--SpringBoot源码(四) 温故而知新,我们来简单回顾一下上 ...

  10. SpringBoot是如何实现自动配置的?--SpringBoot源码(四)

    注:该源码分析对应SpringBoot版本为2.1.0.RELEASE 1 前言 本篇接 助力SpringBoot自动配置的条件注解ConditionalOnXXX分析--SpringBoot源码(三 ...

随机推荐

  1. Codeforces Global Round 11 B. Chess Cheater(贪心)

    题目链接:https://codeforces.com/contest/1427/problem/B 题意 给出一个长为 \(n\) 由 W, L 组成的字符串,如果一个 W 左侧为 W,则它提供 2 ...

  2. UVA 10480 Sabotage (最大流最小割)

    题目链接:点击打开链接 题意:把一个图分成两部分,要把点1和点2分开.隔断每条边都有一个花费,求最小花费的情况下,应该切断那些边. 这题很明显是最小割,也就是最大流.把1当成源点,2当成汇点. 问题是 ...

  3. P3381 [模板] 最小费用最大流

    EK  + dijkstra (2246ms) 开氧气(586ms) dijkstra的势 可以处理负权 https://www.luogu.org/blog/28007/solution-p3381 ...

  4. poj2001 Shortest Prefixes (trie树)

    Description A prefix of a string is a substring starting at the beginning of the given string. The p ...

  5. Bubble Cup 13 - Finals [Online Mirror, unrated, Div. 1] K. Lonely Numbers (数学)

    题意:定义两个数\(a,b\)是朋友,如果:\(gcd(a,b)\),\(\frac{a}{gcd(a,b)}\),\(\frac{b}{gcd(a,b)}\)能构成三角形,现在给你一个正整数\(n\ ...

  6. 记录一些Python中不常用但非常好用的函数

    zfill(): 方法返回指定长度的字符串,原字符串右对齐,前面填充0. print('Helloworld'.zfill(50))0000000000000000000000000000000000 ...

  7. 六、Python集合定义和基本操作方法

    一.集合的定义方法及特点 1.特点: (1)由不同元素组成 #集合由不同元素构成 s={1,2,3,3,4,3,3,} print(s)#运行结果:{1, 2, 3, 4} (2)集合无序 #集合无序 ...

  8. test markdown && 代码高亮

    #include<cstdio> #include<cstring> #include<queue> #include<vector> #include ...

  9. 深入剖析JavaScript中的对象与原始值之间的转换机制

    我们都知道原始值之间是可以互相转换的,但是如果对象转原始值呢? 所有的对象在布尔上下文(context)中均为 true .所以对于对象,不存在 to-boolean 转换, 只有字符串和数值转换. ...

  10. [USACO15JAN]Moovie Mooving G

    [USACO15JAN]Moovie Mooving G 状压难题.不过也好理解. 首先我们根据题意: she does not want to ever visit the same movie t ...