Spring 將 Bean 中繼資料與 Bean 執行個體分離。BeanDefinition 描述如何建立物件,
而 BeanFactory 會在要求物件時套用該定義。ApplicationContext 另外提供協調式啟動、
後處理、事件、資源載入與關閉功能。
Context 重新整理期間會發生什麼 #
AbstractApplicationContext.refresh() 會在應用程式單例可以使用之前準備環境與
Bean 工廠。主要階段如下:
- 準備或取得
BeanFactory,並載入 Bean 定義。 - 在定義仍可變更時呼叫
BeanFactoryPostProcessors,包括組態類別處理。 - 探索並註冊
BeanPostProcessors。 - 初始化 Context 基礎設施,例如訊息解析、事件及 Context 專用資源。
- 建立其餘的非延遲初始化單例 Bean。
- 發布已重新整理的狀態與
ContextRefreshedEvent。
BeanFactoryPostProcessor 會變更中繼資料。相較之下,BeanPostProcessor 會處理
執行個體,可以注入欄位、呼叫生命週期註解,或將 Bean 替換為 Proxy。由於一般應用程式
Bean 可能在所有後處理器註冊前就被建立,因此從工廠後處理器建立一般應用程式 Bean
並不安全。
相依順序與 depends-on
#
容器會先建立 Bean 的建構函式相依項與屬性相依項,再建立相依於它的 Bean。因此, 建構函式注入同時表達必要關係與建立順序:
@Component
final class ReportService {
private final ReportRepository repository;
ReportService(ReportRepository repository) {
this.repository = repository;
}
}當不存在注入關係時,例如初始化共用外部資源,@DependsOn("schemaInitializer")
或 XML 的 depends-on 可以加入順序。對單例 Bean 而言,它也會反轉銷毀順序:
相依 Bean 會在其所相依的 Bean 之前被銷毀。depends-on 會隱藏類別所使用的內容,
因此不應取代實際的具型別相依關係。
執行個體初始化 #
對一般 Bean 而言,Spring 會執行以下操作:
- 建立物件,通常是呼叫建構函式或工廠方法。
- 解析並注入屬性與欄位。
- 呼叫 aware 回呼,包括
BeanNameAware、BeanFactoryAware與ApplicationContextAware。 - 在初始化前呼叫每個
BeanPostProcessor。 - 依序呼叫
@PostConstruct、InitializingBean.afterPropertiesSet(), 然後呼叫已設定的自訂 init 方法。 - 在初始化後呼叫每個
BeanPostProcessor。
Spring 基礎設施透過後處理器實作此序列的部分步驟,因此自訂處理器必須遵守排序契約。 初始化後處理器可能返回 Proxy,而不是原始物件。只有在完整鏈結完成後,呼叫端才會收到 已準備完成、可能已套用建議的物件。
建構函式注入是建立必要不變量最安全的位置。當初始化依賴已注入的屬性或建構函式中
無法取得的容器服務時,適合使用 @PostConstruct。
銷毀與 Context 關閉 #
關閉可設定的 Context 會銷毀受管理的單例。對每個 Bean,Spring 會呼叫 @PreDestroy、
DisposableBean.destroy() 及已設定的自訂 destroy 方法,但會受配接器的重複方法檢查約束。
SmartLifecycle 為需要協調關閉的元件加入分階段的停止回呼。
應用程式應關閉手動建立的 Context,或使用 registerShutdownHook() 註冊關閉勾點。
Spring Boot 會在程序正常關閉時關閉其應用程式 Context。程序突然終止時無法保證回呼執行,
因此持久性正確性不得單獨依賴這些回呼。
原型的擁有權 #
原型作用域表示每次容器要求都會產生新的執行個體。當原型直接注入單例時,只會在建立
單例期間解析一次;該欄位會保留相同的原型執行個體。如果每個操作都需要新的執行個體,
請使用 ObjectProvider<T>、Jakarta Provider<T>、方法注入或作用域 Proxy。
Spring 會完整初始化原型並將其返回給呼叫端,但不會保留該執行個體,也不會在之後呼叫
銷毀回呼。因此,擁有權會移交給接收者。取得持有檔案、Socket 或執行器之原型的程式碼
必須明確關閉它。如果需要集中式清理,自訂 BeanPostProcessor 可以追蹤此類執行個體,
但明確的資源擁有權更加清楚。
評論
在 GitHub 上閱讀或評論(發表評論需要登入)