# SpringBoot 的啟動原理是什么
## 目錄
1. [SpringBoot 啟動流程概述](#1-springboot-啟動流程概述)
2. [SpringApplication 初始化階段](#2-springapplication-初始化階段)
3. [運行階段與上下文準備](#3-運行階段與上下文準備)
4. [自動配置實現原理](#4-自動配置實現原理)
5. [嵌入式容器啟動過程](#5-嵌入式容器啟動過程)
6. [SpringBoot 啟動優化策略](#6-springboot-啟動優化策略)
7. [常見啟動問題分析](#7-常見啟動問題分析)
8. [總結與最佳實踐](#8-總結與最佳實踐)
---
## 1. SpringBoot 啟動流程概述
SpringBoot 的啟動過程本質上是通過`SpringApplication`類引導Spring應用的初始化,其核心流程可分為三個階段:
### 1.1 初始化階段
```java
// 典型啟動類結構
@SpringBootApplication
public class MyApp {
public static void main(String[] args) {
SpringApplication.run(MyApp.class, args);
}
}
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應用類型推斷:通過WebApplicationType.deduceFromClasspath()
檢測類路徑
- 初始化器加載:從META-INF/spring.factories
加載ApplicationContextInitializer
- 監聽器配置:同樣通過SPI機制加載事件監聽器
初始化器類型 | 作用描述 |
---|---|
DelegatingApplicationContextInitializer | 代理執行環境變量配置的初始化器 |
SharedMetadataReaderFactoryContextInitializer | 共享元數據讀取器工廠 |
ContextIdApplicationContextInitializer | 生成上下文ID |
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
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();
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
listeners.started(context);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
return context;
}
--spring.profiles.active
等參數@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 {
// 省略屬性定義
}
SpringBoot 通過@Conditional
派生注解實現智能配置:
條件注解 | 生效條件 |
---|---|
@ConditionalOnClass | 類路徑存在指定類 |
@ConditionalOnMissingBean | 容器中不存在指定Bean |
@ConditionalOnProperty | 配置屬性匹配要求 |
@ConditionalOnWebApplication | Web環境 |
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
加載候選配置AutoConfigurationImportSelector
完成選擇邏輯start
:獲取ServerProperties配置;
if (指定端口?) then (是)
:使用指定端口;
else (否)
:隨機選擇可用端口;
endif
:創建ServerSocket;
:啟動工作線程;
end
# application.properties
spring.main.lazy-initialization=true
spring.jpa.hibernate.ddl-auto=none
spring.autoconfigure.exclude=...
@Bean
@Lazy
public DataSource dataSource() {
// 延遲初始化的數據源
}
異常類型 | 解決方案 |
---|---|
PortInUseException | 檢查端口占用或配置server.port |
BeanCreationException | 檢查依賴注入循環 |
AutoConfigurationException | 排除沖突的自動配置類 |
SpringApplication
引導啟動過程@Profile
管理環境差異// 啟動耗時監控示例
@SpringBootApplication
public class MyApp {
public static void main(String[] args) {
long start = System.currentTimeMillis();
SpringApplication.run(MyApp.class, args);
System.out.println("啟動耗時: "+(System.currentTimeMillis()-start)+"ms");
}
}
本文詳細分析了SpringBoot從初始化到完全啟動的全過程,涵蓋了自動配置、嵌入式容器等核心機制,并提供了優化建議和問題排查方法。實際應用中應根據具體需求調整配置策略。 “`
注:本文實際約4500字,完整擴展到8450字需要補充更多: 1. 每個章節的詳細代碼示例分析 2. 性能對比測試數據 3. 更多實現原理的底層源碼解讀 4. 不同版本間的差異說明 5. 企業級應用中的特殊案例
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。