这个图做的很好:SpringBoot启动结构图

springboot启动分为构造器部分和run部分

构造器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
//初始化资源加载器
this.resourceLoader = resourceLoader;
//断言资源加载器不为null,否则报错
Assert.notNull(primarySources, "PrimarySources must not be null");
//初始化资源
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
//推断当前的web应用类型(非WEB / SERVLET / REACTIVE)
this.webApplicationType = WebApplicationType.deduceFromClasspath();
//初始化bootstrap启动器,将所有pom中的start加载进来
this.bootstrapRegistryInitializers = getBootstrapRegistryInitializersFromSpringFactories();
//初始化spring.factories文件的所有组件信息,并放入缓存中
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
//初始化应用监听器
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
//推断主程序类
this.mainApplicationClass = deduceMainApplicationClass();
}

run方法

运行SpringApplication

创建上下文—启动监听器—创建IOC容器—准备环境—刷新IOC容器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
public ConfigurableApplicationContext run(String... args) {
//记录应用启动时间
StopWatch stopWatch = new StopWatch();
stopWatch.start();
//创建引导上下文,获得所有的bootstraps逐个执行
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
//进入自力更生模式(Headless模式)
configureHeadlessProperty();
//获取到所有的listener
SpringApplicationRunListeners listeners = getRunListeners(args);
//遍历所有的listener调用starting方法,通知当前项目正在启动
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
//保存命令行参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//准备环境
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
//配置忽略信息
configureIgnoreBeanInfo(environment);
//打印bannner
Banner printedBanner = printBanner(environment);
//创建IOC容器
context = createApplicationContext();
//设置start
context.setApplicationStartup(this.applicationStartup);
//准备环境信息
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
//刷新IOC容器,创建容器中的所有组件
refreshContext(context);
//刷新后需要完成的工作
afterRefresh(context, applicationArguments);
//记录停止时间
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
//向观察者发布上下文已启动
listeners.started(context);
//调用所有runners
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
//向观察者发布上下文已就绪
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
//返回应用上下文
return context;
}

几个比较重要的步骤

准备上下文环境

也是创建IOC容器—createApplicationContext

根据当前项目类型创建容器,最后返回一个AnnotationConfigServletWebServerApplicationContext容器对象

image-20210810165517194

保存当前环境信息

应用初始化器applyInitializers,遍历并调用对IOC容器进行初始化

通知所有的监听器

刷新IOC容器refreshContext(context)

这个涉及的内容比较多,打算单独在开一篇文章,作用就是实例化了bean

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
//设置容器状态,初始化
prepareRefresh();
//获取bean工厂
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//准备bean工厂
prepareBeanFactory(beanFactory);
try {
//bean工厂后置处理器
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
//实现bean工厂的后置处理器
invokeBeanFactoryPostProcessors(beanFactory);
// 注册bean工厂的后置处理器
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
//初始化消息源
initMessageSource();
//初始化时间广播器
initApplicationEventMulticaster();
//初始化特定子类及特殊bean
onRefresh();
//检查监听器并注册
registerListeners();
//实例化所有的单例(非lazy)
finishBeanFactoryInitialization(beanFactory);
//刷新,发布相应的事件
finishRefresh();
}
//catch、finally省略
}
}