SpringBoot 的启动过程是一个整合 Spring 核心容器、自动配置、嵌入式服务器等功能的复杂流程,核心目标是 “简化配置、快速启动”。下面从入口类开始,逐步拆解其详细启动步骤:
一、启动入口:@SpringBootApplication
与main
方法
SpringBoot 应用的启动入口是一个带有@SpringBootApplication
注解的类,其中的main
方法是程序的起点:
@SpringBootApplication
public class MyApplication {public static void main(String[] args) {// 核心启动方法SpringApplication.run(MyApplication.class, args);}
}
这行代码看似简单,却包含了初始化 Spring 容器、触发自动配置、启动嵌入式服务器等一系列操作。
二、@SpringBootApplication
注解的核心作用
@SpringBootApplication
是一个 “复合注解”,它整合了三个关键注解,为启动过程奠定基础:
@SpringBootConfiguration
:本质是@Configuration
,标识当前类是一个配置类,允许通过@Bean
定义 Bean。@ComponentScan
:自动扫描当前类所在包及其子包下的@Component
(包括@Service
、@Controller
等)注解类,将其注册为 Spring Bean。@EnableAutoConfiguration
:SpringBoot 的 “灵魂”,开启自动配置功能,通过加载预设的配置类,自动配置 DataSource、Web 服务器等组件。
三、SpringApplication.run()
的详细流程
SpringApplication.run(MyApplication.class, args)
是启动的核心方法,可拆解为两大阶段:SpringApplication
实例初始化 + run()
方法执行。
阶段 1:SpringApplication
实例初始化(准备工作)
当调用SpringApplication.run(...)
时,首先会创建SpringApplication
实例,完成一系列初始化操作:
// 简化的初始化逻辑
public SpringApplication(Class<?>... primarySources) {this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));// 1. 推断应用类型(Servlet/Reactive/Native)this.webApplicationType = WebApplicationType.deduceFromClasspath();// 2. 加载初始化器(ApplicationContextInitializer)setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));// 3. 加载监听器(ApplicationListener)setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));// 4. 推断main方法所在的主类this.mainApplicationClass = deduceMainApplicationClass();
}
关键操作解析:
- 推断应用类型:通过类路径中是否存在
Servlet
、Reactive
相关类,判断是传统 Web 应用(SERVLET
)、响应式 Web 应用(REACTIVE
)还是非 Web 应用(NONE
)。 - 加载初始化器:从
META-INF/spring.factories
文件中读取ApplicationContextInitializer
实现类(用于初始化 Spring 上下文)。 - 加载监听器:同样从
spring.factories
中读取ApplicationListener
实现类(用于监听启动过程中的事件,如环境准备完成、容器刷新等)。
阶段 2:run()
方法执行(核心启动流程)
run()
方法是启动的核心,包含 12 个关键步骤,按顺序执行如下:
步骤 1:启动计时器(记录启动时间)
StopWatch stopWatch = new StopWatch();
stopWatch.start(); // 开始计时
用于统计应用启动总耗时,最终会在控制台输出(如Started MyApplication in 2.345 seconds
)。
步骤 2:初始化运行监听器(SpringApplicationRunListeners
)
通过SpringFactoriesLoader
加载SpringApplicationRunListener
实现类(默认是EventPublishingRunListener
),用于在启动各阶段发布事件(如ApplicationStartingEvent
、ApplicationEnvironmentPreparedEvent
等),触发对应监听器的逻辑。
步骤 3:准备环境(Environment
)
创建并配置Environment
(环境对象),包含:
- 系统环境变量、JVM 参数、命令行参数(
args
)。 - 配置文件(
application.properties
/application.yml
)中的属性。 - 激活的
profiles
(如dev
/test
/prod
)。
过程:
- 为不同应用类型(Servlet/Reactive)创建对应
Environment
实例(如StandardServletEnvironment
)。 - 加载配置文件:默认从
classpath:
、classpath:/config/
、file:./
、file:./config/
等路径读取。 - 处理命令行参数:将
args
中的参数(如--server.port=8081
)添加到环境中,优先级最高。
步骤 4:打印 Banner(启动图标)
默认会在控制台打印 SpringBoot 的 Banner 图标(可通过spring.banner.location
自定义,或设置spring.main.banner-mode=off
关闭)。
步骤 5:创建ApplicationContext
(Spring 容器)
根据应用类型创建对应的ApplicationContext
(Spring 核心容器):
- Servlet 应用:
AnnotationConfigServletWebServerApplicationContext
- Reactive 应用:
AnnotationConfigReactiveWebServerApplicationContext
- 非 Web 应用:
AnnotationConfigApplicationContext
ApplicationContext
是 Spring 的 “大脑”,负责管理 Bean 的生命周期、依赖注入等核心功能。
步骤 6:准备ApplicationContext
(上下文预处理)
为容器设置环境、注册 Bean、应用初始化器等:
- 将步骤 3 中准备好的
Environment
设置到容器中。 - 调用所有
ApplicationContextInitializer
的initialize()
方法,对容器进行自定义初始化(如添加属性源、修改配置等)。 - 发布
ApplicationContextInitializedEvent
事件,通知监听器容器已初始化。 - 注册主配置类:将
@SpringBootApplication
标注的类(如MyApplication
)注册为 Spring 的配置类。
步骤 7:刷新ApplicationContext
(容器核心初始化)
这是 Spring 容器的核心步骤(继承自 Spring 的AbstractApplicationContext
),包含 Bean 的扫描、加载、实例化等关键操作,具体包括:
7.1 执行BeanFactory
的前置处理
初始化容器的BeanFactory
(如DefaultListableBeanFactory
),用于管理 BeanDefinition(Bean 的元数据)。
7.2 执行BeanFactoryPostProcessor
(Bean 工厂后置处理器)
最关键的是自动配置类的加载:
@EnableAutoConfiguration
通过@Import(AutoConfigurationImportSelector.class)
导入自动配置类。AutoConfigurationImportSelector
会从META-INF/spring.factories
中读取EnableAutoConfiguration
对应的配置类(如DataSourceAutoConfiguration
、WebMvcAutoConfiguration
等),并根据@Conditional
条件注解(如@ConditionalOnClass
、@ConditionalOnMissingBean
)筛选出符合当前环境的配置类,注册为 BeanDefinition。
7.3 注册BeanPostProcessor
(Bean 后置处理器)
用于在 Bean 实例化前后进行增强(如 AOP 代理、依赖注入等)。
7.4 初始化消息源(国际化支持)
7.5 初始化事件多播器(用于事件发布)
7.6 初始化容器特定 Bean(子类扩展点)
对 Web 应用而言,这里会触发嵌入式服务器的创建与启动:
ServletWebServerApplicationContext
在onRefresh()
方法中调用createWebServer()
,根据类路径中的依赖(如spring-boot-starter-tomcat
)创建对应的服务器(Tomcat/Undertow/Jetty),并绑定端口(默认 8080)。
7.7 注册监听器到容器
7.8 完成 BeanFactory 初始化(实例化所有非懒加载单例 Bean)
容器会遍历所有 BeanDefinition,实例化单例 Bean(@Lazy
标注的除外),并执行依赖注入(@Autowired
)、初始化方法(@PostConstruct
或InitializingBean
)等。
7.9 发布容器刷新完成事件(ContextRefreshedEvent
)
步骤 8:刷新后的操作
- 清除缓存(如类加载缓存)。
- 发布
ApplicationStartedEvent
事件(通知容器已刷新完成)。
步骤 9:执行Runner
(自定义启动逻辑)
调用所有ApplicationRunner
和CommandLineRunner
的run()
方法,执行启动后的自定义逻辑(如加载初始数据、检查配置等):
ApplicationRunner
:接收ApplicationArguments
参数(解析后的命令行参数)。CommandLineRunner
:直接接收原始String[] args
参数。
步骤 10:发布启动完成事件
发布ApplicationReadyEvent
事件,通知应用已完全启动,可对外提供服务。
步骤 11:停止计时器
stopWatch.stop(); // 停止计时
步骤 12:输出启动日志
打印启动成功日志,包含总耗时、活跃 Profiles 等信息(如Started MyApplication in 2.345 seconds (JVM running for 3.123)
)。
四、核心机制总结
- 自动配置:通过
@EnableAutoConfiguration
和spring.factories
中的配置类,根据依赖和环境自动配置组件(如 DataSource、Web 服务器)。 - 嵌入式服务器:在容器刷新阶段自动创建并启动(如 Tomcat),无需手动部署到外部服务器。
- 事件驱动:通过
SpringApplicationRunListener
和ApplicationListener
在启动各阶段发布事件,支持扩展(如自定义监听器处理特定阶段逻辑)。 - 简化配置:默认扫描路径、默认配置文件、默认 Bean 注册,减少手动配置。
五、流程图总结
main() → SpringApplication实例化 → run()↓
初始化监听器 → 准备环境(配置+参数) → 打印Banner → 创建ApplicationContext↓
准备上下文(设置环境+注册配置类) → 刷新上下文(核心)↓├─ 加载自动配置类 → 注册BeanDefinition├─ 实例化单例Bean → 依赖注入└─ 启动嵌入式服务器(如Tomcat)↓
执行Runner → 发布启动完成事件 → 输出启动日志
通过这一系列流程,SpringBoot 实现了 “零配置(或极简配置)” 的快速启动,让开发者专注于业务逻辑而非框架配置。