Spring 的容器 API 有三個不同層級:Bean 中繼資料、從該中繼資料建立物件的工廠,以及協調工廠與應用程式服務的應用程式上下文。保持這些層級分離,可以更容易理解 Spring 原始碼與擴充點。
Bean 定義與登錄 #
BeanDefinition 是單一 Bean 的可變中繼資料。它記錄 Bean 類別或類別名稱、範圍、建構函式引數、屬性值、限定詞、工廠方法、生命週期方法、角色、來源位置與明確相依性。父子中繼資料關係獨立於 Java 繼承。
常見實作服務於不同的註冊路徑:
RootBeanDefinition表示 Bean 工廠使用的合併定義。ChildBeanDefinition從具名父定義繼承中繼資料。GenericBeanDefinition在合併前可表達獨立或衍生自父項的中繼資料。AnnotatedGenericBeanDefinition暴露已註冊類別的註解中繼資料。ScannedGenericBeanDefinition暴露類別路徑掃描期間讀取的中繼資料,而不先載入元件類別。
BeanDefinitionRegistry 依 Bean 名稱儲存定義。其核心作業是註冊、移除與查詢定義;DefaultListableBeanFactory 與 GenericApplicationContext 是重要實作。
AnnotatedBeanDefinitionReader 註冊明確提供的元件類別:
var context = new GenericApplicationContext();
var reader = new AnnotatedBeanDefinitionReader(context);
reader.register(OrderService.class);
context.refresh();ClassPathBeanDefinitionScanner 搜尋套件中的候選元件並註冊其定義。兩種機制都會套用註解範圍、命名、限定詞、條件與 BeanDefinitionCustomizer 回呼。客製化器可在註冊期間進行針對性的中繼資料變更,而不必實作登錄後處理器。
BeanFactory、FactoryBean 與 ObjectFactory
#
BeanFactory 是執行階段登錄與相依性解析 API。它定位定義、建立 Bean、解析協作者、管理單例識別,並套用生命週期處理器。ListableBeanFactory 加入列舉,HierarchicalBeanFactory 加入父項查找,而 ConfigurableListableBeanFactory 將容器設定暴露給框架基礎設施。應用程式程式碼應依賴其網域協作者,而不是把 getBean() 當作服務定位器呼叫。
三個名稱相似的型別具有不同責任:
BeanFactory是容器。FactoryBean<T>是建立另一個物件的 Bean。查找其名稱會回傳產品;在名稱前加上&會回傳工廠本身。getObjectType()與isSingleton()描述產品。ObjectFactory<T>是具有getObject()的最小回呼。Spring 將它用於延後擷取與內部建立回呼。ObjectProvider<T>以選擇性、有順序與串流式存取擴充模型。
應用程式上下文階層 #
ApplicationContext 擴充 ListableBeanFactory、HierarchicalBeanFactory、MessageSource、ApplicationEventPublisher、ResourcePatternResolver 及相關環境能力。ConfigurableApplicationContext 加入 refresh()、close()、環境設定與存取可設定工廠等生命週期作業。
AbstractApplicationContext 實作重新整理演算法。專用基底類別決定定義如何抵達工廠:
GenericApplicationContext擁有一個內部DefaultListableBeanFactory。可以在一次refresh()呼叫前,透過其登錄 API 註冊定義。AnnotationConfigApplicationContext將一般上下文與AnnotatedBeanDefinitionReader及ClassPathBeanDefinitionScanner結合。其建構函式可以註冊類別或掃描套件,然後重新整理。- 支援 Servlet 的上下文加入 Web 範圍與 Servlet 資源,但保留相同的核心工廠契約。
部分較舊的上下文實作會在重新整理期間重新建立 Bean 工廠,而 GenericApplicationContext 不支援重複的重新整理嘗試。框架擴充必須遵循具體上下文的生命週期,而不是假設每個上下文都能重新整理超過一次。
重新整理與產生的定義 #
註解註冊最初會為提供的類別建立定義。重新整理期間,ConfigurationClassPostProcessor 會剖析 @Configuration、元件掃描、匯入與 @Bean 方法,然後在一般 Bean 實例化前註冊額外定義。登錄後處理器可以在相同階段產生更多定義。Spring 的 AOT 處理可以預先產生註冊程式碼,但產生的定義仍會餵入相同的 Bean 工廠模型。
ApplicationStartup 在不改變生命週期語意的情況下檢測啟動。DefaultApplicationStartup 是低負擔的無操作實作,BufferingApplicationStartup 保留有界的步驟資料,而 FlightRecorderApplicationStartup 發出 Java Flight Recorder 事件。StartupStep 具有名稱、標籤與明確結束;自訂基礎設施應讓標籤保持低成本,因為啟動檢測會在關鍵路徑上執行。
選擇擴充點 #
請使用符合需求的最窄層級:
- 使用
BeanDefinitionCustomizer在註冊時客製化定義。 - 使用
BeanDefinitionRegistryPostProcessor或BeanFactoryPostProcessor加入或轉換中繼資料。 - 使用
BeanPostProcessor攔截實例。 - 使用
FactoryBean建立產生物件的 Bean。 - 在
GenericApplicationContext或應用程式上下文子型別上建立完整協調的容器。
評論
在 GitHub 上閱讀或評論(發表評論需要登入)