我们上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的启动流程图:

最新文章

  1. 【分享】标准springMVC+mybatis项目maven搭建最精简教程
  2. (翻译)编写属于你的jQuery插件
  3. innoDB源码分析--缓冲池
  4. 设计模式之Singleton
  5. C#函数过载
  6. Swift编程语言SequenceType协议中的一些比较有用的接口
  7. Dandelion - Distributed Computing on GPU Clusters
  8. JavaScript创建表格的两种方式
  9. SQLServer错误代码解释
  10. 使用phpexecel类库导出数据
  11. ECSHOP首页调用指定分类下的商品
  12. C#中5中timer的比较
  13. find the mincost route(floyd变形 无向图最小环)
  14. Unity3D之MeleeWeaponTrail武器轨迹插件的使用
  15. Jquery 学习插件第一天
  16. IOS开发(objective-c)~开篇有理
  17. CCNA实验(1) -- 基本配置
  18. 关于wind7重新安装系统后,连接mysql的问题
  19. Run Book Automation - RBA系统介绍
  20. Python网络编程篇之select和epoll

热门文章

  1. 1562: Fun House
  2. HDU - 6287 口算训练 二分+质因数分解
  3. HDU 3416 Marriage Match IV (最短路径&&最大流)
  4. Proud Merchants HDU - 3466 01背包&&贪心
  5. PowerShell随笔2---初始命令
  6. 鸟哥的linux私房菜——第五章学习(Linux的文件权限与目录配置)
  7. 2017CCCC决赛 L1-3. 阅览室
  8. Gym 101480F Frightful Formula(待定系数)题解
  9. sass文件编译(.scss->.css),使用ruby环境,在windows10,koala工具,Error: Invalid GBK character "\xE5"
  10. GitHub Secrets All In One