知識庫 / Spring RSS 訂閱

理解 Spring 中的getBean()

Spring
HongKong
9
01:22 PM · Dec 06 ,2025

1. 簡介

本教程將介紹不同變體的 <em>BeanFactory.getBean()</em> 方法。

簡單來説,正如方法名稱所示,此方法負責從 Spring 容器中檢索 Bean 實例。

2. Spring Bean 配置

首先,我們為測試定義幾個 Spring Bean。提供 Bean 定義給 Spring 容器有多種方式,但在本例中,我們將使用基於註解的 Java 配置:

@Configuration
class AnnotationConfig {

    @Bean(name = {"tiger", "kitty"})
    @Scope(value = "prototype")
    Tiger getTiger(String name) {
        return new Tiger(name);
    }

    @Bean(name = "lion")
    Lion getLion() {
        return new Lion("Hardcoded lion name");
    }

    interface Animal {}
}

我們創建了兩個 Bean。 獅子 具有默認的 Singleton 作用域。 老虎 明確設置為 Prototype 作用域。 此外,我們為每個 Bean 定義了名稱,並在後續請求中使用這些名稱。

3. Bean 獲取 API

<em>BeanFactory</em> 提供了以下五種不同的 getBean() 方法簽名,將在後續子章節中進行詳細分析。

3.1. 通過名稱檢索 Bean

讓我們看看如何使用其名稱檢索 獅子 Bean 實例:

Object lion = context.getBean("lion");

assertEquals(Lion.class, lion.getClass());

在這一變體中,我們提供一個名稱,並返回一個應用程序上下文中具有該名稱的 Object 類的實例。如果找不到具有給定名稱的 Bean,則此 Bean 和所有其他實現都會拋出 NoSuchBeanDefinitionException

主要的缺點是在檢索 Bean 後,我們必須將其強制轉換為所需類型。如果返回的 Bean 的類型與我們期望的不同,則可能會拋出異常

假設我們嘗試使用名稱 “lion”獲取 Tiger。將結果強制轉換為 Tiger 時,將會拋出 ClassCastException

assertThrows(ClassCastException.class, () -> {
    Tiger tiger = (Tiger) context.getBean("lion");
});

3.2. 通過名稱和類型檢索 Bean

這裏我們需要指定請求的 Bean 的名稱和類型:

Lion lion = context.getBean("lion", Lion.class);

相比於之前的方案,這個方案更安全,因為我們能夠立即獲得類型不匹配的信息:

assertThrows(BeanNotOfRequiredTypeException.class, () -> 
    context.getBean("lion", Tiger.class));
}

3.3. 通過類型檢索 Bean

使用第三種 `<em getBean() 變體,只需指定 Bean 的類型即可:

Lion lion = context.getBean(Lion.class);

在這種情況下,我們需要特別注意一個可能存在歧義的潛在結果:

assertThrows(NoUniqueBeanDefinitionException.class, () -> 
    context.getBean(Animal.class));
}

在上面的示例中,由於 LionTiger 都實現了 Animal 接口,僅僅指定類型並不能明確地確定結果。因此,我們得到了 NoUniqueBeanDefinitionException

3.4. 通過構造函數參數檢索 Bean

除了 Bean 名稱之外,我們還可以傳遞構造函數參數:

Tiger tiger = (Tiger) context.getBean("tiger", "Siberian");

此方法略有不同,因為它僅適用於具有原型作用域的 Bean。

對於單例 Bean,我們將收到 BeanDefinitionStoreException

因為原型 Bean 在從應用程序容器中請求時,每次都會返回一個新的實例,因此在調用 getBean() 時,我們可以提供運行時構造參數:

Tiger tiger = (Tiger) context.getBean("tiger", "Siberian");
Tiger secondTiger = (Tiger) context.getBean("tiger", "Striped");

assertEquals("Siberian", tiger.getName());
assertEquals("Striped", secondTiger.getName());

如我們所見,每個 Tiger 都根據我們請求 Bean 時指定的第二個參數獲得不同的名稱。

3.5. 通過構造參數檢索 Bean

此方法類似於前一個方法,但我們需要將類型而不是名稱作為第一個參數傳遞:

Tiger tiger = context.getBean(Tiger.class, "Shere Khan");

assertEquals("Shere Khan", tiger.getName());

與通過構造參數按名稱檢索 Bean 類似,此方法僅適用於具有原型作用域的 Bean

4. 使用注意事項

儘管 <em>BeanFactory </em> 接口中定義了該方法,但 <em>getBean() </em> 方法通常通過 <em>ApplicationContext </em> 訪問。通常情況下,我們不希望在我們的程序中直接使用 <em>getBean()</em> 方法。

豆子應該由容器管理。如果我們想使用它們,我們應該依賴於依賴注入,而不是直接調用 `ApplicationContext.getBean() 這樣可以避免將應用程序邏輯與框架相關細節混合在一起。

5. 結論

在本快速教程中,我們詳細介紹了 getBean() 方法的所有實現,這些實現來自 BeanFactory 接口,並對每種實現進行了優缺點分析。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.