知識庫 / Spring RSS 訂閱

禁用 Spring 自動裝配,僅針對特定 Bean

Spring
HongKong
8
10:54 AM · Dec 06 ,2025

1. 概述

在開發 Spring Boot 項目時,我們可能會遇到需要禁用 Bean 自動裝配的需求。本教程將通過一些用例,向您展示如何在 Spring Boot 應用程序中禁用 Bean 自動裝配。

2. 禁用自動裝配

首先,我們明確一點,禁用 Bean 的自動裝配意味着當 Spring Boot 應用啓動時,它不會嘗試為特定類創建 Bean。 通常,我們使用 @Component 註解在類上,讓 Spring 創建 Bean,並使用 @Autowired 將該 Bean 注入到聲明的字段中。

現在,這種情況何時會發生呢?讓我們討論兩個用例。

2.1. 在我們的源代碼中

Spring 的核心任務之一是維護我們的 Bean。它創建、維護和銷燬 Bean,而無需我們付出很大的努力。但是,在某些情況下,我們可能有一個類,不想在啓動時創建該類的 Bean。導致這種情況的場景包括循環依賴、延遲加載、多環境配置以及管理原型/請求範圍的 Bean,以避免不必要的初始化並提高性能。

使用 @Autowired 標註在變量上,可以讓 Spring 注入該類型的 Bean。這是一個必不可少的步驟,但有時我們不想在啓動時自動注入某些 Bean。要實現這一點,我們可以簡單地使用 @Autowired(required = false)。通過這樣做,我們告訴 Spring 不要自動注入該變量,只需忽略它。

2.2. 使用第三方庫

讓我們理解第二個用例。假設我們正在使用一個第三方庫,並且需要創建一個類的 Bean。但是,有一個問題! Bean 類依賴於一個內部依賴,我們不想使用自動注入。此外,由於它是第三方庫,我們不能修改它的代碼。

讓我們考慮以下代碼:

@Component
public class TestBean {
    @Autowired
    private TestDependency dependency;
    ...
}

這個類,TestBean,存在於第三方庫中,我們想要創建一個對該類的Bean,但我們不想創建一個對TestDependency的Bean。現在,我們的用例就完成了!

通常,第一反應是使用@Bean註解,如下所示:

@Bean
public TestBean testBean() {
    return Library.createBean();
}

如果我們使用一個測試用例來測試它:

@Autowired
private ApplicationContext applicationContext;

@Test
void whenTestBeanIsCraetedWithBeanAnnotation_thenItShouldFail() {
    TestBean testBean = applicationContext.getBean(TestBean.class);
    Assertions.assertNotNull(testBean);
}

它將無法成功運行,並拋出異常:缺少符合條件的 ‘TestDependency’ 類型的 Bean,預期至少有一個 Bean 能夠作為自動注入候選 Bean。

那麼,我們如何解決這個問題呢?

解決此問題的辦法是使用 FactoryBean 類創建 Bean。

3. FactoryBean

Factory Bean 是 一個充當其他 Bean 創建工廠的 Bean,並使用 Spring IOC 容器實例化它們

這種方法在複雜的對象創建場景中非常有用,使得僅使用簡單的 XML 或基於註解的配置變得困難。它通常用於創建代理實例,例如 AOP 代理,其中需要向對象添加動態行為。

此外,它在集成第三方庫方面發揮着關鍵作用,這些庫需要自定義初始化邏輯,這也是我們的第二個用例。

它提供了對 Bean 實例化進行精細控制,例如管理智能緩存或確定創建的 Bean 是否應遵循單例作用域。

讓我們看看如何實現 FactoryBean 接口。讓我們以簡單的方式瞭解如何將其應用於 TestBean

public class TestBeanFactoryBean implements FactoryBean<TestBean> {
    @Override
    public TestBean getObject() throws Exception {
        return new TestBean();
    }

    @Override
    public Class<?> getObjectType() {
        return TestBean.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}

因此,在上述代碼中,我們提供了一種邏輯,用於在 getObject() 方法中創建 Bean,通過 getObjectType() 方法指定類和作用域,並使用 isSingleton() 方法控制。我們通過這些方法來控制 Bean 的創建。

現在,讓我們瞭解如何幫助我們解決問題:

public static <T> FactoryBean<T> createBean(T bean) {
    return new FactoryBean<T>() {
        public T getObject() throws Exception {
            return bean;
        }

        public Class<?> getObjectType() {
            return bean.getClass();
        }

        public boolean isSingleton() {
            return true;
        }
    };
}

@Bean
static FactoryBean<TestBean> testBean() {
    return createBean(new TestBean());
}

在這裏,我們定義瞭如何使用匿名類創建簡單的 new TestBean() 。然而,這種邏輯通常來自第三方庫。

一個問題可能是為什麼我們將 bean 包裝在 FactoryBean 中?為什麼不直接返回 new TestBean() 呢?答案在於,這樣做會產生 TestDependency bean 未找到的錯誤。

在進行上述更改後,如果在第 2.2 節中再次運行測試用例,它將成功運行。

4. 結論

在本文中,我們探討了需要禁用 Bean 自動裝配的場景。我們還看到了如何使用 FactoryBean 接口以一種新的方式創建 Bean 並解決這些問題。

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

發佈 評論

Some HTML is okay.