SpringBoot 启动时,第一步是推断那么第二部执行run方法的过程中都有哪些操作
·
Spring Boot 应用启动时,入口通常是:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
这个 SpringApplication.run(...) 方法是整个启动流程的核心。我们可以将启动过程分为两个主要阶段:
一、推断阶段(Inference Phase)
这是在 new SpringApplication(...) 构造器中完成的,包括:
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.addCommandLineProperties = true;
this.addConversionService = true;
this.headless = true;
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));
this.properties.setWebApplicationType(WebApplicationType.deduceFromClasspath());
this.bootstrapRegistryInitializers = new ArrayList(this.getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = this.deduceMainApplicationClass();
}
- 推断主配置类(primary source)
- 推断 Web 应用类型(
WebApplicationType) - 设置初始化器(
ApplicationContextInitializer) - 设置监听器(
ApplicationListener) - 推断主类(main class)
这部分是“第一步”,我们重点分析第二步。
二、执行 run 方法的详细流程(Execution Phase)
我们以 Spring Boot 2.7.x / 3.x 的源码为基础,分析 SpringApplication.run(String... args) 方法内部执行的关键步骤。
源码入口(简化版):
public ConfigurableApplicationContext run(String... args) {
// 1. 创建并启动 StopWatch(计时器)
StopWatch stopWatch = new StopWatch();
stopWatch.start();
// 2. 初始化上下文容器引用
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
// 3. 配置 Headless 模式
configureHeadlessProperty();
// 4. 获取并启动监听器
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
// 5. 创建并处理 ApplicationArguments
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 6. 准备 Environment(环境变量、配置文件等)
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
configureIgnoreBeanInfo(environment);
// 7. 打印 Banner(可选)
Banner printedBanner = printBanner(environment);
// 8. 创建 ApplicationContext(根据 Web 类型决定是 Servlet/Reactive/None)
context = createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
// 9. 准备上下文(加载 Bean 定义、注册单例等)
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
// 10. 刷新上下文(核心:触发 Spring 容器的 refresh)
refreshContext(context);
// 11. 刷新后处理(空方法,可扩展)
afterRefresh(context, applicationArguments);
// 12. 停止计时器,发布启动完成事件
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
// 13. 通知监听器:启动完成
listeners.started(context, stopWatch.getTotalTimeMillis());
// 14. 调用 Runner(CommandLineRunner / ApplicationRunner)
callRunners(context, applicationArguments);
// 15. 通知监听器:运行中(running)
listeners.running(context);
return context;
} catch (Throwable ex) {
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
}
三、关键步骤详解(结合原理)
1. 创建 Bootstrap Context(引导上下文)
- Spring Boot 2.4+ 引入了
BootstrapContext,用于支持早期配置(如配置中心拉取配置)。 - 通常用于
spring-cloud场景,在普通 Spring Boot 中可能为空。
2. 启动监听器(SpringApplicationRunListeners)
- 加载
META-INF/spring.factories中定义的SpringApplicationRunListener。 - 默认实现是
EventPublishingRunListener,它会将启动过程中的各个阶段包装成事件(如ApplicationStartingEvent)并发布到事件总线。
3. 准备 Environment
- 创建
Environment(StandardServletEnvironment / StandardReactiveWebEnvironment / StandardEnvironment)。 - 绑定命令行参数、系统属性、配置文件(application.properties / yml)。
- 触发
EnvironmentPostProcessor对 Environment 进行后处理(如 Spring Cloud Config)。 - 发布
ApplicationEnvironmentPreparedEvent。
4. 创建 ApplicationContext
- 根据
webApplicationType创建:AnnotationConfigServletWebServerApplicationContext(Servlet Web)AnnotationConfigReactiveWebServerApplicationContext(Reactive Web)AnnotationConfigApplicationContext(非 Web)
5. prepareContext(准备上下文)
- 将 Environment 设置到 ApplicationContext。
- 应用
ApplicationContextInitializer(用户自定义初始化逻辑)。 - 注册单例 Bean(如
springApplicationArguments、springBootBanner)。 - 加载主配置类(即
@SpringBootApplication标注的类)为 BeanDefinition。 - 发布
ApplicationContextInitializedEvent。
6. refreshContext(刷新上下文)
- 调用
AbstractApplicationContext.refresh(),这是 Spring Framework 的核心方法。 - 关键子步骤包括:
invokeBeanFactoryPostProcessors():处理@Configuration、@ComponentScan、@Import、@PropertySource等。registerBeanPostProcessors():注册 Bean 后处理器。initMessageSource()、initApplicationEventMulticaster()。onRefresh():内嵌 Web 容器启动点(如 Tomcat 启动在此处)。registerListeners():注册事件监听器。finishBeanFactoryInitialization():实例化所有非懒加载的单例 Bean。finishRefresh():发布ContextRefreshedEvent,启动 Lifecycle 组件。
注意:
refreshContext()内部还会调用registerShutdownHook()注册 JVM 关闭钩子。
7. callRunners
- 找出所有
CommandLineRunner和ApplicationRunner的 Bean。 - 按
@Order或Ordered排序后依次执行。 - 这是应用完全启动后、对外提供服务前的最后扩展点。
8. 发布 running 事件
- 发布
ApplicationReadyEvent,表示应用已准备好处理请求。
四、总结:run 方法的核心流程图(简化)
run()
├─ 创建 BootstrapContext
├─ 启动监听器 → ApplicationStartingEvent
├─ 准备 Environment → ApplicationEnvironmentPreparedEvent
├─ 创建 ApplicationContext
├─ prepareContext → ApplicationContextInitializedEvent
├─ refreshContext(Spring 容器刷新)
│ ├─ 加载 Bean 定义
│ ├─ 实例化 Bean
│ └─ 启动内嵌 Web 容器(如 Tomcat)
├─ afterRefresh(空钩子)
├─ callRunners(执行 CommandLineRunner / ApplicationRunner)
└─ listeners.running() → ApplicationReadyEvent
五、扩展建议
-
若想干预启动流程,可通过:
- 实现
ApplicationContextInitializer - 实现
ApplicationListener<...Event> - 实现
EnvironmentPostProcessor - 实现
CommandLineRunner/ApplicationRunner
- 实现
-
调试技巧:在
SpringApplication.run()处打断点,逐步跟踪上述流程。
更多推荐



所有评论(0)