我们上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. 2019牛客暑期多校训练营(第二场) H-Second Large Rectangle(单调栈)

    题意:给出由01组成的矩阵,求求全是1的次大子矩阵. 思路: 单调栈 全是1的最大子矩阵的变形,不能直接把所有的面积存起来然后排序取第二大的,因为次大子矩阵可能在最大子矩阵里面,比如: 1 0 0 1 ...

  2. c++ stl nth_element 原理解析

    nth_element是stl中的一个库函数,它会使迭代器nth所指的元素与整个[first,last)完整排序后.同一个位置的元素同值.即找到完整排序时第n位的正确值. 但这个函数与完整排序的区别在 ...

  3. 2020ICPC·小米 网络选拔赛第一场 J.Matrix Subtraction (贪心,二维差分)

    题意:给一个\(nXm\)的矩阵,可以选取\(aXb\)的子矩阵,使子矩阵中的所有元素减一,问最后是否能使矩阵中所有元素变为\(0\). 题解:首先贪心,我们看最左上角的元素,如果\(g[1][1]\ ...

  4. c语言文件的读取和写入

    文件打开类型: 文件打开输出就用: 1 #include <stdio.h> 2 3 int main() 4 { 5 FILE *fp = NULL; 6 7 fp = fopen(&q ...

  5. Leetcode(29)-两数相除

    给定两个整数,被除数 dividend 和除数 divisor.将两数相除,要求不使用乘法.除法和 mod 运算符. 返回被除数 dividend 除以除数 divisor 得到的商. 示例 1: 输 ...

  6. Vue Cheat Sheet & Nuxt.js Cheat Sheet

    Vue Cheat Sheet & Nuxt.js Cheat Sheet Vue Cheat Sheet https://www.vuemastery.com/pdf/Vue-Essenti ...

  7. 微软收购 GitHub

    微软收购 GitHub 微软收购 GitHub震惊业界:引发开发者信任问题 https://news.cnblogs.com/n/598432/ GitLab refs xgqfrms 2012-20 ...

  8. API & YApi

    API & YApi 接口管理服务 YApi http://yapi.demo.qunar.com/ https://ued.qunar.com/ build bug https://gith ...

  9. Parcel all in one

    Parcel all in one Parcel https://parceljs.org/ # cli $ yarn global add parcel-bundler $ npm install ...

  10. useState & useEffect

    useState & useEffect https://overreacted.io/zh-hans/a-complete-guide-to-useeffect/ https://react ...