1. Spring Boot启动流程深度解析
作为一名长期使用Spring Boot框架的后端开发者,我经常被问到Spring Boot应用启动时究竟发生了什么。今天,我将从源码层面详细剖析Spring Boot的启动机制,帮助大家理解这个"黑盒子"内部的工作原理。
Spring Boot的启动过程可以概括为两个核心阶段:SpringApplication实例化和run()方法执行。我们先从一个典型的启动类开始:
java复制@SpringBootApplication
@Slf4j
public class ApplicationMain {
public static void main(String[] args) {
ConfigurableApplicationContext ctx = SpringApplication.run(ApplicationMain.class, args);
}
}
这段简单的代码背后,Spring Boot完成了大量复杂的工作。让我们深入源码,一步步拆解这个过程。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. SpringApplication初始化过程
2.1 构造函数核心逻辑
启动过程首先会创建SpringApplication实例,这是整个启动流程的起点:
java复制public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return new SpringApplication(primarySources).run(args);
}
构造函数中完成了几个关键操作:
java复制this.resourceLoader = resourceLoader;
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
// 1. 推断Web应用类型
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 2. 加载ApplicationContextInitializer
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 3. 加载ApplicationListener
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
// 4. 推断主启动类
this.mainApplicationClass = deduceMainApplicationClass();
这里有几个关键点值得注意:
-
Web应用类型推断:Spring Boot会检查类路径下是否存在特定的类来判断应用类型(Servlet、Reactive或非Web应用)。这个判断直接影响后续ApplicationContext的类型选择。
-
工厂加载机制:
getSpringFactoriesInstances方法通过spring.factories文件加载扩展组件,这是Spring Boot自动配置的核心机制之一。 -
启动类推断:通过分析调用栈来定位主启动类,这种方法虽然巧妙但也可能导致在某些特殊场景下识别失败。
2.2 应用类型推断细节
Web应用类型推断是通过检查类路径中是否存在特定类来完成的:
java复制static WebApplicationType deduceFromClasspath() {
if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null)
&& !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
&& !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
return WebApplicationType.REACTIVE;
}
for (String className : SERVLET_INDICATOR_CLASSES) {
if (!ClassUtils.isPresent(className, null)) {
return WebApplicationType.NONE;
}
}
return WebApplicationType.SERVLET;
}
这种设计使得Spring Boot能够自动适应不同类型的应用,无需手动配置。
3. run()方法执行流程
3.1 run()方法整体结构
run()方法是Spring Boot启动的核心,其基本结构如下:
java复制public ConfigurableApplicationContext run(String... args) {
// 1. 计时开始
StopWatch stopWatch = new StopWatch();
stopWatch.start();
