1. SpringBoot 启动原理深度解析
作为一名长期使用SpringBoot的开发者,我经常被问到:"为什么一行简单的SpringApplication.run()就能启动整个应用?"今天,我将从源码层面,带你彻底理解SpringBoot的启动机制。
1.1 从入口开始
一个标准的SpringBoot应用入口如下:
java复制@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
这看似简单的两行代码背后,隐藏着SpringBoot精心设计的启动流程。让我们先拆解@SpringBootApplication这个注解。
1.2 @SpringBootApplication:三合一的魔法
@SpringBootApplication实际上是一个组合注解,它包含了三个核心注解:
java复制@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
// ...
}
这三个注解各司其职:
@SpringBootConfiguration:标识这是一个配置类,等价于@Configuration@EnableAutoConfiguration:开启自动配置的核心注解@ComponentScan:启用组件扫描,默认扫描当前包及其子包
实际开发中,我们也可以单独使用这三个注解替代
@SpringBootApplication,但组合注解更加简洁。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. SpringApplication.run() 的完整流程
2.1 启动阶段分解
SpringApplication.run()方法的执行可以分为以下几个关键阶段:
- 初始化阶段:创建SpringApplication实例
- 环境准备:加载配置,处理命令行参数
- 容器创建:根据应用类型创建对应的ApplicationContext
- 容器刷新:最核心的阶段,完成自动配置、Bean加载等
- 后置处理:执行Runner接口实现,发布事件
让我们深入每个阶段的实现细节。
2.2 初始化阶段:SpringApplication构造
在调用run()方法前,首先会创建SpringApplication实例:
java复制public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
this.webApplicationType = WebApplicationType.deduceFromClasspath();
this.bootstrapRegistryInitializers = new ArrayList<>(
getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
关键点解析:
