本文主要讲解SpringBoot的启动流程
环境:SpringBoot 2.4.2
首先,我们在主启动类加上断点,开启debug

step into,直到显示这一行

从这一行可以看出来,SpringBoot的启动流程大体上分为两步,第一步是创建SpringApplication,第二步是运行SpringApplication
我们进入创建SpringApplication的流程,首先进入SpringApplication的构造方法

在构造方法内部,
首先保存了一些信息
判定了当前应用的类型为Servlet(使用ClassUtils工具类判定)
设定bootstrappers初始引导启动器,保存在List<Bootstrapper> bootstrappers中:从classpath的spring.factories文件中去找org.springframework.boot.Bootstrapper(在此项目中,没有找到)
从spring.factories中找ApplicationContextInitializer.class应用初始化器,保存在List<ApplicationContextInitializer<?>> initializers中(找到了7个)
从spring.factories中找ApplicationListener.class应用监听器,保存在List<ApplicationListener<?>> listeners中(找到了9个)
调用deduceMainApplicationClass方法寻找主程序类,寻找方法是在堆栈中找到有main方法的第一个类,就是应用的主程序类(在此项目中就是DemoApplication)
总之,创建SpringApplication的过程就是将一些信息保存在SpringApplication类中
在创建完SpringApplication对象后,就进行SpringApplication的运行工作,我们进入run方法

创建StopWatch用来监控应用的开始和停止
记录应用的启动时间
调用createBootstrapContext方法创建引导上下文:对之前保存的bootstrappers挨个遍历执行intitialize方法来完成对引导启动器上下文环境的设置
让当前应用进入headless模式:java.awt.headless
获取所有RunListener运行监听器:从spring.factories中找SpringApplicationRunListener.class
遍历所有的RunListener,调用starting方法。相当于通知所有感兴趣系统正在启动的人,项目正在starting,这一部分涉及到自定义SpringBoot启动过程

保存命令行参数,保存到ApplicationArguments实例中
调用prepareEnvironment方法准备环境:

调用getOrCreateEnvironment方法得到环境对象:如果环境信息已经存在,直接返回使用;如果环境信息没有,则创建环境信息对象,不同的应用创建不同的环境信息,SERVLET -> StandardServletEnvironment,REACTIVE -> StandardReactiveWebEnvironment,default -> StandardEnvironment
配置环境信息对象

首先添加ConversionService,里面包括了很多的类型转换器,然后执行configurePropertySources(environment, args);加载外部配置源,读取所有配置源的属性值
绑定环境信息
所有监听器都挨个调用environmentPrepared方法:表示通知所有监听器当前环境已经准备完成
在准备完环境信息之后,调用printBanner方法打印banner

在运行完这一行之后,在命令行界面可以看到banner信息

接下来就到了关键的部分,SpringBoot要创建IOC容器,也就是ApplicationContext

首先根据项目类型创建容器

调用prepareContext方法准备IOC容器ApplicationContext的基本信息
首先保存之前设置的环境信息
进行IOC容器的后置处理流程
执行applyInitializers(context);应用之前获取的初始化器(第1章,步骤4):遍历所有的ApplicationContextInitializer,挨个调用对应的initialize方法,对IOC容器进行初始化扩展功能
执行listeners.contextPrepared(context);,遍历之前获得的所有listener应用监听器(2.1,步骤5),只有1个,EventPublishingRunListener,调用对应的contextPrepared方法,通知所有监听器contextPrepared
给容器中添加一些特殊的bean

执行listeners.contextLoaded(context);,通知所有监听器contextLoaded

执行refreshContext(context);刷新IOC容器
这一步骤会创建出容器中的所有组件,具体的过程参考Spring底层原理
执行afterRefresh(context, applicationArguments);,表示容器刷新后完成的工作
执行listeners.started(context);,通知所有监听器started
调用所有的Runner
获取容器中的ApplicationRunner
获取容器中的CommandLineRunner
合并所有Runner并按照@Order进行排序
遍历所有Runner,调用对应的run方法
如果以上步骤出现了异常,SpringBoot会执行listeners.failed(context, exception);,通知所有监听器应用failed

listeners.running(context);,调用监听器的running方法,通知所有监听器应用正在runninglisteners.failed(context, exception);至此,IOC容器创建完成
SpringBoot启动流程比较复杂,期间涉及到许多的监听器和事件监听机制,需要深入学习
原文:https://www.cnblogs.com/yoshi/p/14279306.html