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 實現了 “零配置(或極簡配置)” 的快速啟動,讓開發者專注于業務邏輯而非框架配置。