SpringBoot启动过程:加载配置,初始化环境,创建应用上下文,执行自动配置,扫描组件,初始化Bean,启动内嵌服务器,完成应用启动,最后运行CommandLineRunner或ApplicationRunner接口的实现类。

1、启动入口
SpringBoot应用的启动入口通常是main方法,调用SpringApplication.run():
java
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
2、SpringApplication初始化
SpringApplication的初始化过程:
java
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
this.webApplicationType = WebApplicationType.deduceFromClasspath();
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
关键步骤:
- 推断应用类型(WEB/NONE)
- 加载
META-INF/spring.factories中的ApplicationContextInitializer和ApplicationListener - 推断主配置类
3、run()方法执行流程
run()方法是整个启动过程的核心:
java
public ConfigurableApplicationContext run(String... args) {
// 1. 创建并启动计时器
StopWatch stopWatch = new StopWatch();
stopWatch.start();
// 2. 准备环境
ConfigurableApplicationContext context = null;
ConfigurableEnvironment environment = prepareEnvironment(...);
// 3. 打印Banner
Banner printedBanner = printBanner(environment);
// 4. 创建应用上下文
context = createApplicationContext();
// 5. 准备上下文
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
// 6. 刷新上下文(核心)
refreshContext(context);
// 7. 启动后处理
afterRefresh(context, applicationArguments);
// 8. 触发启动完成事件
listeners.started(context);
// 9. 执行Runner
callRunners(context, applicationArguments);
stopWatch.stop();
return context;
}
4、关键步骤详解
4.1 环境准备
prepareEnvironment()方法:
- 创建环境对象(StandardServletEnvironment/StandardEnvironment)
- 配置PropertySources和Profiles
- 处理命令行参数
4.2 创建应用上下文
createApplicationContext()根据应用类型创建不同的上下文:
- Web应用:AnnotationConfigServletWebServerApplicationContext
- 非Web应用:AnnotationConfigApplicationContext
4.3 刷新上下文
refreshContext()最终调用AbstractApplicationContext.refresh(),这是Spring容器的核心初始化过程:
java
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 1. 准备刷新
prepareRefresh();
// 2. 获取BeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 3. 准备BeanFactory
prepareBeanFactory(beanFactory);
try {
// 4. 后置处理BeanFactory
postProcessBeanFactory(beanFactory);
// 5. 调用BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(beanFactory);
// 6. 注册BeanPostProcessor
registerBeanPostProcessors(beanFactory);
// 7. 初始化MessageSource
initMessageSource();
// 8. 初始化事件广播器
initApplicationEventMulticaster();
// 9. 初始化特殊Bean
onRefresh();
// 10. 注册监听器
registerListeners();
// 11. 初始化非延迟加载的单例Bean
finishBeanFactoryInitialization(beanFactory);
// 12. 完成刷新
finishRefresh();
}
// ...
}
}
4.4 SpringBoot的自动配置
invokeBeanFactoryPostProcessors()会调用ConfigurationClassPostProcessor处理@Configuration类,其中关键的是处理@SpringBootApplication:
java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { /* ... */ })
public @interface SpringBootApplication {
// ...
}
@EnableAutoConfiguration会导入AutoConfigurationImportSelector,它从META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports加载自动配置类。
5、自定义启动过程
自定义Banner
在resources目录下创建banner.txt:
___ _ __ ___| |_ ___ _ __
/ __| '_ \ / _ \ __/ _ \ '__|
\__ \ |_) | __/ || __/ |
|___/ .__/ \___|\__\___|_|
|_|
这个图案大家想放什么都可以。
自定义ApplicationContextInitializer:
java
public class MyInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
System.out.println("MyInitializer initialize...");
}
}
在META-INF/spring.factories中注册:
org.springframework.context.ApplicationContextInitializer=com.example.MyInitializer
自定义SpringApplicationRunListener:
java
public class MyRunListener implements SpringApplicationRunListener {
public MyRunListener(SpringApplication application, String[] args) {}
@Override
public void starting() {
System.out.println("MyRunListener starting...");
}
// 实现其他方法...
}
在META-INF/spring.factories中注册:
org.springframework.boot.SpringApplicationRunListener=com.example.MyRunListener
自定义自动配置
创建自动配置类:
java
@Configuration
@ConditionalOnClass(MyService.class)
@EnableConfigurationProperties(MyProperties.class)
public class MyAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public MyService myService(MyProperties properties) {
return new MyService(properties);
}
}
在 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 中注册:
com.example.MyAutoConfiguration
6、启动过程关键扩展点
- ApplicationContextInitializer: 在ConfigurableApplicationContext刷新之前执行
- ApplicationListener: 监听各种应用事件
- BeanFactoryPostProcessor: 修改BeanDefinition
- BeanPostProcessor: 修改Bean实例
- CommandLineRunner/ApplicationRunner: 应用启动后执行
7、关于调试的技巧
要深入理解启动过程,可以:
- 在关键类上设置断点:
- SpringApplication.run()
- AbstractApplicationContext.refresh()
- ConfigurationClassPostProcessor.processConfigBeanDefinitions()
- 查看自动配置报告:
- 启动时添加
--debug参数 - 或设置
logging.level.org.springframework.boot.autoconfigure=DEBUG
- 启动时添加
通过以上分析,你应该对SpringBoot的启动过程有了全面的了解。实际开发中,可以根据需要自定义各个扩展点来满足特定需求。