BeanFactory API

BeanFactory API 為 Spring 的 IoC 功能提供了底層基礎。其特定契約主要用於與 Spring 的其他部分和相關的第三方框架整合,而其 DefaultListableBeanFactory 實作是較高層級 GenericApplicationContext 容器中的主要委派。

BeanFactory 和相關介面(例如 BeanFactoryAwareInitializingBeanDisposableBean)是其他框架元件的重要整合點。由於不需要任何註解甚至反射,它們允許容器及其元件之間進行非常有效率的互動。應用程式層級的 Bean 可以使用相同的回呼介面,但通常更偏好宣告式相依性注入,可以透過註解或程式化組態。

請注意,核心 BeanFactory API 層級及其 DefaultListableBeanFactory 實作不會對組態格式或要使用的任何元件註解做出假設。所有這些風格都是透過擴充功能(例如 XmlBeanDefinitionReaderAutowiredAnnotationBeanPostProcessor)引入的,並以共用的 BeanDefinition 物件作為核心元資料表示形式進行操作。這是使 Spring 容器如此彈性和可擴充的本質。

BeanFactoryApplicationContext

本節說明 BeanFactoryApplicationContext 容器層級之間的差異,以及對啟動的影響。

您應該使用 ApplicationContext,除非您有充分的理由不這樣做,GenericApplicationContext 及其子類別 AnnotationConfigApplicationContext 是自訂啟動的常用實作。這些是 Spring 核心容器的主要進入點,適用於所有常見目的:載入組態檔、觸發類別路徑掃描、以程式設計方式註冊 Bean 定義和註解類別,以及(自 5.0 起)註冊功能性 Bean 定義。

由於 ApplicationContext 包含 BeanFactory 的所有功能,因此通常建議使用 ApplicationContext 而不是純粹的 BeanFactory,除非在需要完全控制 Bean 處理的情況下。在 ApplicationContext(例如 GenericApplicationContext 實作)中,會依慣例偵測到幾種 Bean(也就是說,依 Bean 名稱或 Bean 類型 — 特別是後處理器),而純粹的 DefaultListableBeanFactory 對任何特殊 Bean 都持不可知論的態度。

對於許多擴充的容器功能,例如註解處理和 AOP 代理,BeanPostProcessor 擴充點至關重要。如果您僅使用純粹的 DefaultListableBeanFactory,則預設情況下不會偵測和啟動此類後處理器。這種情況可能會令人困惑,因為您的 Bean 組態實際上沒有任何問題。相反地,在這種情況下,需要透過額外的設定來完全啟動容器。

下表列出了 BeanFactoryApplicationContext 介面和實作提供的功能。

表 1. 功能矩陣
功能 BeanFactory ApplicationContext

Bean 實例化/組裝

整合生命週期管理

自動 BeanPostProcessor 註冊

自動 BeanFactoryPostProcessor 註冊

方便的 MessageSource 存取(用於國際化)

內建 ApplicationEvent 發布機制

若要使用 DefaultListableBeanFactory 明確註冊 Bean 後處理器,您需要以程式設計方式呼叫 addBeanPostProcessor,如下列範例所示

  • Java

  • Kotlin

DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
// populate the factory with bean definitions

// now register any needed BeanPostProcessor instances
factory.addBeanPostProcessor(new AutowiredAnnotationBeanPostProcessor());
factory.addBeanPostProcessor(new MyBeanPostProcessor());

// now start using the factory
val factory = DefaultListableBeanFactory()
// populate the factory with bean definitions

// now register any needed BeanPostProcessor instances
factory.addBeanPostProcessor(AutowiredAnnotationBeanPostProcessor())
factory.addBeanPostProcessor(MyBeanPostProcessor())

// now start using the factory

若要將 BeanFactoryPostProcessor 應用於純粹的 DefaultListableBeanFactory,您需要呼叫其 postProcessBeanFactory 方法,如下列範例所示

  • Java

  • Kotlin

DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(new FileSystemResource("beans.xml"));

// bring in some property values from a Properties file
PropertySourcesPlaceholderConfigurer cfg = new PropertySourcesPlaceholderConfigurer();
cfg.setLocation(new FileSystemResource("jdbc.properties"));

// now actually do the replacement
cfg.postProcessBeanFactory(factory);
val factory = DefaultListableBeanFactory()
val reader = XmlBeanDefinitionReader(factory)
reader.loadBeanDefinitions(FileSystemResource("beans.xml"))

// bring in some property values from a Properties file
val cfg = PropertySourcesPlaceholderConfigurer()
cfg.setLocation(FileSystemResource("jdbc.properties"))

// now actually do the replacement
cfg.postProcessBeanFactory(factory)

在兩種情況下,明確的註冊步驟都不方便,這就是為什麼在 Spring 支援的應用程式中,各種 ApplicationContext 變體比純粹的 DefaultListableBeanFactory 更受歡迎的原因,尤其是在典型的企業設定中,依賴 BeanFactoryPostProcessorBeanPostProcessor 實例來擴充容器功能時。

AnnotationConfigApplicationContext 已註冊所有常見的註解後處理器,並且可能會透過組態註解(例如 @EnableTransactionManagement)在幕後引入其他處理器。在 Spring 基於註解的組態模型的抽象層級,Bean 後處理器的概念僅成為容器的內部細節。