1.前言
最近一直在看Springboot和springcloud代码,看了将近20多天,对这两个系统的认知总算是入了门。后续应该会有一个系列的文章,本文就先从Springboot的启动入手.
2.容器初始化
上面的代码是Springboot的入口,现在从run方法进去
点击进来后到了这里就会分成两步
1.生成一个SpringApplication对象
2.调用生成的对象的run方法
【2.1】我们先看SpringApplication的构造器是如何生成一个SpringApplication对象
1.推断程序类型,推断规则在2.1.1
2.查找ApplicationContextInitializer的实现类,ApplicationContextInitializer是Spring框架的接口,在ApplicationContext的初始化之前,需要逐一调用ApplicationContextInitializer的实现类的initialize方法。
3.查找中ApplicationListener的实现类,Springboot大量的采用了事件监听机制,ApplicationListener负责将监听事件并广播出去。后续我们会详细讲解
【2.1.1】判断程序类型
至此SpringApplication构造初始化就完成了。
3.容器启动
调用生成的对象的run方法
【3.1】记录时间
Springboot内部记录流程节点花费时间的工具类
【3.2】获取ApplicationRunListener
这里通过SpringApplicationRunListeners 封装了多个SpringApplicationRunListener。在容器的启动过程中,springboot将这个过程分为了五步
started(run方法执行的时候立马执行;对应事件的类型是ApplicationStartedEvent)
environmentPrepared(ApplicationContext创建之前并且环境信息准备好的时候调用;对应事件的类型是ApplicationEnvironmentPreparedEvent)
contextPrepared(ApplicationContext创建好并且在source加载之前调用一次;没有具体的对应事件)
contextLoaded(ApplicationContext创建并加载之后并在refresh之前调用;对应事件的类型是ApplicationPreparedEvent)
finished(run方法结束之前调用;对应事件的类型是ApplicationReadyEvent或ApplicationFailedEvent)
同时,SpringApplicationRunListener 只有一个实现类 EventPublishingRunListener,所以上述5个步骤的最终实现都会在 EventPublishingRunListener中。
我们看看start方法
这里的 ApplicationStartedEvent 继承 SpringApplicationEvent
再看publishEvent是如何把Event推送出去的
看到这边,发现最后发送event的还是ApplicationListener
这里一整套的封装,就是为了这边发送事件
【3.3】创建容器
【3.3.1】创建Environment
【3.3.2】创建容器
【3.3.3】SpringApplication的init
找到所有ApplicationContextInitializer的实现类,调用他们的initialize方法。
【3.3.4】加载mainsource到容器
【3.3.5】refresh,BeanFactory的设置,BeanFactoryPostProcessor接口的执行、BeanPostProcessor接口的执行、自动化配置类的解析、条件注解的解析、国际化的初始化
【3.4】容器创建之后
【3.4.1】Runer实现类
调用ApplicationRunner和CommandLineRunner的实现类
4.Springboot启动的扩展
上述讲了springboot的启动流程,那如果我们想在启动的时候自定义一些操作,可以考虑以下几种方式。
【4.1】对容器的操作
实现 ApplicationContextInitializer 接口,重写initialize方法
需要注意的是,这个bean需要在META-INF/spring.factories中注册上才可以被扫描到
【4.2】监听5大事件
实现 ApplicationListener
【4.3】实现 ApplicationRunner 或者 CommandLineRunner
以上,就是Springboot的启动流程,里面还有几处细节,后续会慢慢更新