Spring Boot啟動流程及源碼實現深度解析
一、啟動流程概述
Spring Boot的啟動流程圍繞SpringApplication
類展開,核心流程可分為以下幾個階段:
- 初始化階段:推斷應用類型,加載
ApplicationContextInitializer
和ApplicationListener
- 環境準備:加載配置文件和命令行參數
- 上下文創建:實例化
ApplicationContext
- 上下文刷新:執行
refresh()
方法完成Bean加載 - 后置處理:執行
CommandLineRunner
和ApplicationRunner
二、源碼解析
1. 入口類
@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);}
}
2. SpringApplication初始化
// SpringApplication.java
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {return new SpringApplication(primarySource).run(args);
}public SpringApplication(Class<?>... primarySources) {this(null, primarySources);
}private SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {this.resourceLoader = resourceLoader;this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));this.webApplicationType = WebApplicationType.deduceFromClasspath(); // 推斷應用類型setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)); // 加載InitializerssetListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); // 加載Listenersthis.mainApplicationClass = deduceMainApplicationClass();
}
關鍵步驟解析:
deduceFromClasspath()
通過類路徑判斷應用類型(Servlet/Reactive/None)- 從
META-INF/spring.factories
加載初始化器和監聽器
3. run()方法核心流程
public ConfigurableApplicationContext run(String... args) {StopWatch stopWatch = new StopWatch();stopWatch.start();ConfigurableApplicationContext context = null;SpringApplicationRunListeners listeners = getRunListeners(args);listeners.starting();try {ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);configureIgnoreBeanInfo(environment);Banner printedBanner = printBanner(environment);// 創建應用上下文context = createApplicationContext();context.setEnvironment(environment);// 準備上下文prepareContext(context, environment, listeners, applicationArguments, printedBanner);// 刷新上下文(核心)refreshContext(context);// 后置處理afterRefresh(context, applicationArguments);stopWatch.stop();// 發布啟動完成事件listeners.started(context);callRunners(context, applicationArguments);} catch (Throwable ex) {handleRunFailure(context, ex, listeners);throw new IllegalStateException(ex);}listeners.running(context);return context;
}
三、關鍵階段詳解
1. 環境準備(prepareEnvironment)
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,ApplicationArguments applicationArguments) {ConfigurableEnvironment environment = getOrCreateEnvironment();configureEnvironment(environment, applicationArguments.getSourceArgs());ConfigurationPropertySources.attach(environment);listeners.environmentPrepared(environment); // 發布環境準備事件bindToSpringApplication(environment);return environment;
}
- 加載
application.properties/yml
文件 - 處理命令行參數
--
開頭的參數 - 觸發
ApplicationEnvironmentPreparedEvent
事件
2. 上下文創建(createApplicationContext)
根據應用類型創建不同的上下文:
protected ConfigurableApplicationContext createApplicationContext() {return this.applicationContextFactory.create(this.webApplicationType);
}// 默認實現
ApplicationContextFactory DEFAULT = (webApplicationType) -> {try {switch (webApplicationType) {case SERVLET:return new AnnotationConfigServletWebServerApplicationContext();case REACTIVE:return new AnnotationConfigReactiveWebServerApplicationContext();default:return new AnnotationConfigApplicationContext();}} catch (Exception ex) {throw new IllegalStateException(...);}
};
3. 上下文刷新(refreshContext)
private void refreshContext(ConfigurableApplicationContext context) {refresh(context);if (this.registerShutdownHook) {try {context.registerShutdownHook();} catch (AccessControlException ex) {// Not allowed in some environments.}}
}protected void refresh(ApplicationContext applicationContext) {((AbstractApplicationContext) applicationContext).refresh();
}
最終調用AbstractApplicationContext.refresh()
,這是Spring容器的核心方法:
public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {prepareRefresh();ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();prepareBeanFactory(beanFactory);// ... [省略其他步驟]finishRefresh(); // 觸發ContextRefreshedEvent}
}
四、關鍵擴展點
1. ApplicationContextInitializer
public interface ApplicationContextInitializer<C extends ConfigurableApplicationContext> {void initialize(C applicationContext);
}
- 執行時機:上下文準備階段(prepareContext)
- 配置方式:通過
spring.factories
或SpringApplication.addInitializers()
2. ApplicationRunner/CommandLineRunner
@Component
public class DemoRunner implements ApplicationRunner {@Overridepublic void run(ApplicationArguments args) {// 應用啟動后執行}
}
- 執行順序:通過
@Order
注解控制 - 執行時機:上下文刷新完成后
五、總結
Spring Boot的啟動流程通過智能的自動配置和擴展機制,顯著簡化了Spring應用的初始化過程。理解其核心流程和關鍵擴展點,可以幫助開發者:
- 深入排查啟動過程中的問題
- 實現自定義的初始化邏輯
- 優化應用啟動性能
- 擴展框架的核心功能
建議結合源碼調試工具,通過斷點跟蹤SpringApplication.run()
的執行過程,可以更直觀地理解各階段的實現細節。
流程圖文字描述:
main()
└─? SpringApplication.run()├─? 初始化應用類型和擴展組件├─? 準備環境(加載配置)├─? 創建ApplicationContext├─? 準備上下文(Bean定義加載)├─? 刷新上下文(Bean初始化)├─? 執行Runner接口└─? 完成啟動
通過以上分析,讀者可以系統地掌握Spring Boot的啟動機制及其實現原理。實際開發中可結合具體需求,合理使用擴展點進行定制化開發。