# 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 应用生命周期事件(如 ApplicationStartedEventApplicationReadyEvent 等),执行响应逻辑。

Spring Boot应用的启动类:

@SpringBootApplication
public class SpringbootStarterTestApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootStarterTestApplication.class, args);
    }

}
1
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();
    }
    ....

}
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

2.run方法

  1. 记录应用启动时间

  2. 创建引导上下文 createBootstrapContext()

    • 获取所有 bootstrappers,逐个执行 initialize(),完成引导上下文环境设置
  3. 进入 headless 模式:设置 java.awt.headless 模式

  4. 获取所有 RunListener(运行监听器)

    • 通过 getSpringFactoriesInstancesspring.factories 中加载 SpringApplicationRunListener
  5. 遍历 SpringApplicationRunListener,调用 starting() 方法

    • 通知所有监听器:应用正在启动中
  6. 保存命令行参数:封装为 ApplicationArguments

  7. 准备环境 prepareEnvironment()

    • 创建 / 返回基础环境对象(如 StandardServletEnvironment
    • 读取所有配置源的配置属性值
    • 绑定环境信息,调用 listener.environmentPrepared(),通知监听器环境已准备完成
  8. 创建 IOC 容器 createApplicationContext()

    • 根据应用类型(如 Servlet)创建对应容器,如 AnnotationConfigServletWebServerApplicationContext
  9. 准备 IOC 容器基本信息 prepareContext()

    • 保存环境信息到容器
    • 执行 IOC 容器后置处理流程
    • 执行 ApplicationContextInitializer:遍历所有初始化器,调用 initialize() 对容器做扩展
    • 调用 listener.contextPrepared():通知监听器容器已准备好
    • 调用 listener.contextLoaded():通知监听器容器已加载完成
  10. 刷新 IOC 容器 refreshContext()

    • 解析并创建容器中所有组件(Spring 注解驱动的 Bean)
  11. 容器刷新后工作 afterRefresh()

  12. 通知监听器 started:调用 listeners.started(context),告知应用已启动完成

  13. 执行所有 runners callRunners()

    • 从容器中获取 ApplicationRunnerCommandLineRunner
    • 合并所有 runner 并按 @Order 排序
    • 遍历所有 runner,调用 run() 方法
  14. 异常处理

    • 若以上步骤出现异常,调用 listener.failed(),通知监听器启动失败
  15. 通知监听器 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);
    }

    ...
}
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
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.... ");
    }
}
1
2
3
4
5
6
7
8
9
10
11

MyApplicationListener (监听应用的生命周期,如 ApplicationStartedEventApplicationReadyEvent 等)

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...");
    }
}
1
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....");
    }
}
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

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...");
    }
}
1
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....");
    }
}
1
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
1
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....
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

最近更新: 9/19/2026, 1:27:08 PM
编程NOTE   |