# 09.SpringBoot-原理解析
# 1.SpringApplication创建初始化流程
1.创建SpringApplication
保存一些信息
判定当前应用的类型(Servlet)
加载 bootstrappers(初始启动引导器)
- 从
META-INF/spring.factories文件中加载所有org.springframework.boot.Bootstrapper实现类,存入List<Bootstrapper>。 - 作用:在应用启动最早期执行一些引导性操作(如环境预处理、配置加载等)。
- 从
加载 ApplicationContextInitializer(容器初始化器)
- 从
spring.factories文件中查找所有ApplicationContextInitializer实现类,存入List<ApplicationContextInitializer<?>>。 - 作用:在
ApplicationContext刷新(refresh())之前,对容器做自定义初始化(如注册 Bean 定义、激活配置文件等)。
- 从
加载 ApplicationListener(应用监听器)
- 从
spring.factories文件中查找所有ApplicationListener实现类,存入List<ApplicationListener<?>>。 - 作用:监听 Spring Boot 应用生命周期事件(如
ApplicationStartedEvent、ApplicationReadyEvent等),执行响应逻辑。
- 从
Spring Boot应用的启动类:
@SpringBootApplication
public class SpringbootStarterTestApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootStarterTestApplication.class, args);
}
}
2
3
4
5
6
7
8
public class SpringApplication {
....
public SpringApplication(Class<?>... primarySources) {
this((ResourceLoader)null, primarySources);
}
public SpringApplication(@Nullable ResourceLoader resourceLoader, Class<?>... primarySources) {
this.addCommandLineProperties = true;
this.addConversionService = true;
this.headless = true;
this.initializers = new ArrayList();
this.listeners = new ArrayList();
this.additionalProfiles = Collections.emptySet();
this.applicationContextFactory = ApplicationContextFactory.DEFAULT;
this.applicationStartup = ApplicationStartup.DEFAULT;
this.properties = new ApplicationProperties();
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "'primarySources' must not be null");
this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
//WebApplicationType是枚举类,有NONE,SERVLET,REACTIVE,
//下行webApplicationType是SERVLET
this.properties.setWebApplicationType(WebApplicationType.deduce());
//初始启动引导器,去spring.factories文件中找org.springframework.boot.Bootstrapper(没找到则为空)
this.bootstrapRegistryInitializers = new ArrayList(this.getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
//去spring.factories找 ApplicationContextInitializer
this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
//去spring.factories找 ApplicationListener
this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = this.deduceMainApplicationClass();
}
....
}
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

2.run方法
记录应用启动时间
创建引导上下文
createBootstrapContext()- 获取所有
bootstrappers,逐个执行initialize(),完成引导上下文环境设置
- 获取所有
进入 headless 模式:设置
java.awt.headless模式获取所有
RunListener(运行监听器)- 通过
getSpringFactoriesInstances从spring.factories中加载SpringApplicationRunListener
- 通过
遍历
SpringApplicationRunListener,调用starting()方法- 通知所有监听器:应用正在启动中
保存命令行参数:封装为
ApplicationArguments准备环境
prepareEnvironment()- 创建 / 返回基础环境对象(如
StandardServletEnvironment) - 读取所有配置源的配置属性值
- 绑定环境信息,调用
listener.environmentPrepared(),通知监听器环境已准备完成
- 创建 / 返回基础环境对象(如
创建 IOC 容器
createApplicationContext()- 根据应用类型(如 Servlet)创建对应容器,如
AnnotationConfigServletWebServerApplicationContext
- 根据应用类型(如 Servlet)创建对应容器,如
准备 IOC 容器基本信息
prepareContext()- 保存环境信息到容器
- 执行 IOC 容器后置处理流程
- 执行
ApplicationContextInitializer:遍历所有初始化器,调用initialize()对容器做扩展 - 调用
listener.contextPrepared():通知监听器容器已准备好 - 调用
listener.contextLoaded():通知监听器容器已加载完成
刷新 IOC 容器
refreshContext()- 解析并创建容器中所有组件(Spring 注解驱动的 Bean)
容器刷新后工作
afterRefresh()通知监听器
started:调用listeners.started(context),告知应用已启动完成执行所有 runners
callRunners()- 从容器中获取
ApplicationRunner和CommandLineRunner - 合并所有 runner 并按
@Order排序 - 遍历所有 runner,调用
run()方法
- 从容器中获取
异常处理
- 若以上步骤出现异常,调用
listener.failed(),通知监听器启动失败
- 若以上步骤出现异常,调用
通知监听器
running:调用listeners.running(context),告知应用正在运行- 若
running阶段出现问题,继续调用listener.failed(),通知启动失败
- 若
public class SpringApplication {
...
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();//开始计时器
stopWatch.start();//开始计时
//1.
//创建引导上下文(Context环境)createBootstrapContext()
//获取到所有之前的 bootstrappers 挨个执行 intitialize() 来完成对引导启动器上下文环境设置
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
//2.到最后该方法会返回这context
ConfigurableApplicationContext context = null;
//3.让当前应用进入headless模式
configureHeadlessProperty();
//4.获取所有 RunListener(运行监听器),为了方便所有Listener进行事件感知
SpringApplicationRunListeners listeners = getRunListeners(args);
//5. 遍历 SpringApplicationRunListener 调用 starting 方法;
// 相当于通知所有感兴趣系统正在启动过程的人,项目正在 starting。
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
//6.保存命令行参数 ApplicationArguments
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//7.准备环境
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
configureIgnoreBeanInfo(environment);
/*打印标志
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.4.2)
*/
Banner printedBanner = printBanner(environment);
// 创建IOC容器(createApplicationContext())
// 根据项目类型webApplicationType(NONE,SERVLET,REACTIVE)创建容器,
// 当前会创建 AnnotationConfigServletWebServerApplicationContext
context = createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
//8.准备ApplicationContext IOC容器的基本信息
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
//9.刷新IOC容器,创建容器中的所有组件,Spring框架的内容
refreshContext(context);
//该方法没内容,大概为将来填入
afterRefresh(context, applicationArguments);
stopWatch.stop();//停止计时
if (this.logStartupInfo) {//this.logStartupInfo默认是true
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
//10.
listeners.started(context);
//11.调用所有runners
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
//13.
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
//12.
listeners.running(context);
}
catch (Throwable ex) {
//13.
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
return context;
}
//1.
private DefaultBootstrapContext createBootstrapContext() {
DefaultBootstrapContext bootstrapContext = new DefaultBootstrapContext();
this.bootstrappers.forEach((initializer) -> initializer.intitialize(bootstrapContext));
return bootstrapContext;
}
//3.
private void configureHeadlessProperty() {
//this.headless默认为true
System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS,
System.getProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, Boolean.toString(this.headless)));
}
private static final String SYSTEM_PROPERTY_JAVA_AWT_HEADLESS = "java.awt.headless";
//4.
private SpringApplicationRunListeners getRunListeners(String[] args) {
Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
//getSpringFactoriesInstances 去 spring.factories 找 SpringApplicationRunListener
return new SpringApplicationRunListeners(logger,
getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args),
this.applicationStartup);
}
//7.准备环境
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
// Create and configure the environment
//返回或者创建基础环境信息对象,如:StandardServletEnvironment, StandardReactiveWebEnvironment
ConfigurableEnvironment environment = getOrCreateEnvironment();
//配置环境信息对象,读取所有的配置源的配置属性值。
configureEnvironment(environment, applicationArguments.getSourceArgs());
//绑定环境信息
ConfigurationPropertySources.attach(environment);
//7.1 通知所有的监听器当前环境准备完成
listeners.environmentPrepared(bootstrapContext, environment);
DefaultPropertiesPropertySource.moveToEnd(environment);
configureAdditionalProfiles(environment);
bindToSpringApplication(environment);
if (!this.isCustomEnvironment) {
environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
deduceEnvironmentClass());
}
ConfigurationPropertySources.attach(environment);
return environment;
}
//8.
private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
//保存环境信息
context.setEnvironment(environment);
//IOC容器的后置处理流程
postProcessApplicationContext(context);
//应用初始化器
applyInitializers(context);
//8.1 遍历所有的 listener 调用 contextPrepared。
//EventPublishRunListenr通知所有的监听器contextPrepared
listeners.contextPrepared(context);
bootstrapContext.close(context);
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// Add boot specific singleton beans
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
if (beanFactory instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory) beanFactory)
.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
if (this.lazyInitialization) {
context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
}
// Load the sources
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
load(context, sources.toArray(new Object[0]));
//8.2
listeners.contextLoaded(context);
}
//11.调用所有runners
private void callRunners(ApplicationContext context, ApplicationArguments args) {
List<Object> runners = new ArrayList<>();
//获取容器中的 ApplicationRunner
runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
//获取容器中的 CommandLineRunner
runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
//合并所有runner并且按照@Order进行排序
AnnotationAwareOrderComparator.sort(runners);
//遍历所有的runner。调用 run 方法
for (Object runner : new LinkedHashSet<>(runners)) {
if (runner instanceof ApplicationRunner) {
callRunner((ApplicationRunner) runner, args);
}
if (runner instanceof CommandLineRunner) {
callRunner((CommandLineRunner) runner, args);
}
}
}
//13.
private void handleRunFailure(ConfigurableApplicationContext context, Throwable exception,
SpringApplicationRunListeners listeners) {
try {
try {
handleExitCode(context, exception);
if (listeners != null) {
//14.
listeners.failed(context, exception);
}
}
finally {
reportFailure(getExceptionReporters(context), exception);
if (context != null) {
context.close();
}
}
}
catch (Exception ex) {
logger.warn("Unable to close ApplicationContext", ex);
}
ReflectionUtils.rethrowRuntimeException(exception);
}
...
}
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218

# 核心总结
Spring Boot 启动流程本质是{环境准备 → 容器创建 → 组件加载 → 事件通知}的完整链路:
- 所有扩展组件(
Bootstrapper/Initializer/Listener/Runner)都通过 SPI 机制(spring.factories) 加载,实现高度可插拔 - 事件驱动贯穿全程:通过
SpringApplicationRunListener在关键节点(starting/environmentPrepared/contextPrepared/started/running)通知外部组件,实现生命周期感知 - 容器刷新是核心:
refreshContext()完成所有 Bean 的实例化、依赖注入和初始化,是 Spring IOC 容器的核心工作
# 2.自定义监听组件
MyApplicationContextInitializer(初始化执行)
package com.demo.config;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
public class MyApplicationContextInitializer implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
System.out.println("MyApplicationContextInitializer ....initialize.... ");
}
}
2
3
4
5
6
7
8
9
10
11
MyApplicationListener (监听应用的生命周期,如 ApplicationStartedEvent、ApplicationReadyEvent 等)
package com.demo.config;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
public class MyApplicationListener implements ApplicationListener {
@Override
public void onApplicationEvent(ApplicationEvent event) {
System.out.println("MyApplicationListener.....onApplicationEvent...");
}
}
2
3
4
5
6
7
8
9
10
11
MySpringApplicationRunListener(运行监听器,通知所有监听器运行的怎么样了)
package com.demo.config;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringApplicationRunListener;
import org.springframework.boot.bootstrap.ConfigurableBootstrapContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import java.time.Duration;
public class MySpringApplicationRunListener implements SpringApplicationRunListener {
private SpringApplication application;
public MySpringApplicationRunListener(SpringApplication application, String[] args){
this.application = application;
}
@Override
public void starting(ConfigurableBootstrapContext bootstrapContext) {
System.out.println("MySpringApplicationRunListener....starting....");
}
@Override
public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) {
System.out.println("MySpringApplicationRunListener....environmentPrepared....");
}
@Override
public void started(ConfigurableApplicationContext context, @Nullable Duration timeTaken) {
System.out.println("MySpringApplicationRunListener....started....");
}
@Override
public void ready(ConfigurableApplicationContext context, @Nullable Duration timeTaken) {
System.out.println("MySpringApplicationRunListener....ready....");
}
@Override
public void contextPrepared(ConfigurableApplicationContext context) {
System.out.println("MySpringApplicationRunListener....contextPrepared....");
}
@Override
public void contextLoaded(ConfigurableApplicationContext context) {
System.out.println("MySpringApplicationRunListener....contextLoaded....");
}
@Override
public void failed(ConfigurableApplicationContext context, Throwable exception) {
System.out.println("MySpringApplicationRunListener....failed....");
}
}
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
MyApplicationRunner和MyCommandLineRunner(调用run方法)
package com.demo.config;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Order(1)
@Component//放入容器
public class MyApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("MyApplicationRunner...run...");
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.demo.config;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
/**
* 应用启动做一个一次性事情
*/
@Order(2)
@Component//放入容器
public class MyCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("MyCommandLineRunner....run....");
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
spring.factories
org.springframework.context.ApplicationContextInitializer=\
com.demo.config.MyApplicationContextInitializer
org.springframework.context.ApplicationListener=\
com.demo.config.MyApplicationListener
org.springframework.boot.SpringApplicationRunListener=\
com.demo.config.MySpringApplicationRunListener
2
3
4
5
6
7
8
结果
MyApplicationContextInitializer ....initialize....
MyApplicationListener.....onApplicationEvent...
MySpringApplicationRunListener....contextPrepared....
2026-03-14T16:49:58.458+08:00 INFO 8864 --- [springboot-starter-test] [ main] c.demo.SpringbootStarterTestApplication : Starting SpringbootStarterTestApplication using Java 24.0.2 with PID 8864 (D:\code1\StarterTest\springboot-starter-test\target\classes started by 25133 in D:\code1\StarterTest)
2026-03-14T16:49:58.460+08:00 INFO 8864 --- [springboot-starter-test] [ main] c.demo.SpringbootStarterTestApplication : No active profile set, falling back to 1 default profile: "default"
MyApplicationListener.....onApplicationEvent...
MySpringApplicationRunListener....contextLoaded....
2026-03-14T16:49:59.098+08:00 INFO 8864 --- [springboot-starter-test] [ main] o.s.boot.tomcat.TomcatWebServer : Tomcat initialized with port 8888 (http)
2026-03-14T16:49:59.108+08:00 INFO 8864 --- [springboot-starter-test] [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2026-03-14T16:49:59.108+08:00 INFO 8864 --- [springboot-starter-test] [ main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/11.0.18]
2026-03-14T16:49:59.134+08:00 INFO 8864 --- [springboot-starter-test] [ main] b.w.c.s.WebApplicationContextInitializer : Root WebApplicationContext: initialization completed in 623 ms
2026-03-14T16:49:59.373+08:00 INFO 8864 --- [springboot-starter-test] [ main] o.s.boot.tomcat.TomcatWebServer : Tomcat started on port 8888 (http) with context path '/'
MyApplicationListener.....onApplicationEvent...
MyApplicationListener.....onApplicationEvent...
2026-03-14T16:49:59.377+08:00 INFO 8864 --- [springboot-starter-test] [ main] c.demo.SpringbootStarterTestApplication : Started SpringbootStarterTestApplication in 1.242 seconds (process running for 1.687)
MyApplicationListener.....onApplicationEvent...
MyApplicationListener.....onApplicationEvent...
MySpringApplicationRunListener....started....
MyApplicationRunner...run...
MyCommandLineRunner....run....
MyApplicationListener.....onApplicationEvent...
MyApplicationListener.....onApplicationEvent...
MySpringApplicationRunListener....ready....
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23