知識庫 / Spring / Spring Boot RSS 訂閱

Spring 組件掃描

Spring Boot
HongKong
9
01:42 PM · Dec 06 ,2025

1. 概述

本教程將介紹 Spring 中的組件掃描。 在使用 Spring 時,我們可以對類進行註解,將其轉換為 Spring Bean。 此外,我們可以告訴 Spring 在哪裏搜索這些註解類,並非所有類都需要成為該運行時的 Bean。

當然,組件掃描有一些默認設置,但我們也可以自定義搜索包。

首先,讓我們看看默認設置。

2. <em @ComponentScan> 無參數配置

2.1. 使用 @ComponentScan 在 Spring 應用中

使用 Spring 時,我們使用 @ComponentScan 註解以及 @Configuration 註解來指定我們想要掃描的包。 @ComponentScan 沒有參數時,它會告訴 Spring 掃描當前包及其所有子包。

假設我們有以下 @Configurationcom.baeldung.componentscan.springapp 包中:

@Configuration
@ComponentScan
public class SpringComponentScanApp {
    private static ApplicationContext applicationContext;

    @Bean
    public ExampleBean exampleBean() {
        return new ExampleBean();
    }

    public static void main(String[] args) {
        applicationContext = 
          new AnnotationConfigApplicationContext(SpringComponentScanApp.class);

        for (String beanName : applicationContext.getBeanDefinitionNames()) {
            System.out.println(beanName);
        }
    }
}

此外,我們還擁有 CatDog 組件,位於 com.baeldung.componentscan.springapp.animals 包中:

package com.baeldung.componentscan.springapp.animals;
// ...
@Component
public class Cat {}
package com.baeldung.componentscan.springapp.animals;
// ...
@Component
public class Dog {}

最後,我們有 Rose 組件,位於 com.baeldung.componentscan.springapp.flowers 包中:

package com.baeldung.componentscan.springapp.flowers;
// ...
@Component
public class Rose {}

<em>main()</em> 方法的輸出將包含 <em>com.baeldung.componentscan.springapp</em> 包及其子包的所有 Bean:

springComponentScanApp
cat
dog
rose
exampleBean

請注意,主應用程序類也是一個 Bean,因為它被標記為 ,這本身就是一個

我們還應該注意的是,主應用程序類和配置類不一定相同。如果它們不同,我們不必在意主應用程序類放在哪裏。 只有配置類的位置重要,因為默認情況下組件掃描從其包開始

最後,請注意,在我們的示例中, 等效於:

@ComponentScan(basePackages = "com.baeldung.componentscan.springapp")

basePackages參數是一個包或包的數組,用於掃描。

2.2. 在 Spring Boot 應用中使用 @ComponentScan

Spring Boot 的訣竅在於許多事情會自動發生。我們使用 @SpringBootApplication> 標註,但它實際上是三個標註的組合:

@Configuration
@EnableAutoConfiguration
@ComponentScan

讓我們在 com.baeldung.componentscan.springbootapp 包中創建類似的結構。 這一次,主應用程序將是:

package com.baeldung.componentscan.springbootapp;
// ...
@SpringBootApplication
public class SpringBootComponentScanApp {
    private static ApplicationContext applicationContext;

    @Bean
    public ExampleBean exampleBean() {
        return new ExampleBean();
    }

    public static void main(String[] args) {
        applicationContext = SpringApplication.run(SpringBootComponentScanApp.class, args);
        checkBeansPresence(
          "cat", "dog", "rose", "exampleBean", "springBootComponentScanApp");

    }

    private static void checkBeansPresence(String... beans) {
        for (String beanName : beans) {
            System.out.println("Is " + beanName + " in ApplicationContext: " + 
              applicationContext.containsBean(beanName));
        }
    }
}

所有其他包和類保持不變,我們只需將它們複製到附近的 com.baeldung.componentscan.springbootapp 包中。

Spring Boot 掃描包的方式與我們之前的示例類似。 讓我們查看輸出:

Is cat in ApplicationContext: true
Is dog in ApplicationContext: true
Is rose in ApplicationContext: true
Is exampleBean in ApplicationContext: true
Is springBootComponentScanApp in ApplicationContext: true

我們之所以在第二個示例中僅檢查 Bean 的存在(而不是打印出所有 Bean),是因為輸出結果會過於龐大。

這是因為隱式的 @EnableAutoConfiguration 註解,導致 Spring Boot 自動創建了大量的 Bean,並依賴於 pom.xml 文件中的依賴項。

3. 使用 @ComponentScan 帶有參數

現在,讓我們自定義掃描路徑。例如,假設我們想要排除 Rose Bean。

3.1. 使用 @ComponentScan 指定特定包

我們可以通過多種方式實現這一點。首先,我們可以更改基礎包:

@ComponentScan(basePackages = "com.baeldung.componentscan.springapp.animals")
@Configuration
public class SpringComponentScanApp {
   // ...
}

現在輸出將會是:

springComponentScanApp
cat
dog
exampleBean

讓我們來看看背後的內容:

  • springComponentScanApp 被創建,因為它是一個作為參數傳遞給 AnnotationConfigApplicationContext 的配置。
  • exampleBean 是在配置中配置的 Bean。
  • catdog 位於指定的 com.baeldung.componentscan.springapp.animals 包中。

以上所有自定義選項在 Spring Boot 中同樣適用。我們可以結合使用 @ComponentScan@SpringBootApplication,結果將相同:

@SpringBootApplication
@ComponentScan(basePackages = "com.baeldung.componentscan.springbootapp.animals")

3.2. 使用 @ComponentScan 指定多個包

Spring 提供了一種便捷的方式來指定多個包名。 要做到這一點,我們需要使用字符串數組。

數組中的每個字符串都表示一個包名:

@ComponentScan(basePackages = {"com.baeldung.componentscan.springapp.animals", "com.baeldung.componentscan.springapp.flowers"})

當然,以下是翻譯後的內容:

或者,自 Spring 4.1.1 版本起,我們可以使用逗號、分號或空格來分隔包列表

@ComponentScan(basePackages = "com.baeldung.componentscan.springapp.animals;com.baeldung.componentscan.springapp.flowers")
@ComponentScan(basePackages = "com.baeldung.componentscan.springapp.animals,com.baeldung.componentscan.springapp.flowers")
@ComponentScan(basePackages = "com.baeldung.componentscan.springapp.animals com.baeldung.componentscan.springapp.flowers")

3.3. 使用 @ComponentScan 排除指定類

另一種方法是使用過濾器,指定要排除的類的模式:

@ComponentScan(excludeFilters = 
  @ComponentScan.Filter(type=FilterType.REGEX,
    pattern="com\\.baeldung\\.componentscan\\.springapp\\.flowers\\..*"))

我們還可以選擇不同的過濾類型,因為該標註支持多種靈活的選項,用於過濾掃描的類

@ComponentScan(excludeFilters = 
  @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = Rose.class))

4. 默認包

我們應該避免將 <em >@Configuration</em> 類放在默認包中(即不指定包名)。如果這樣做,Spring 會掃描 classpath 中所有 jar 包中的所有類,這會導致錯誤,並且應用程序可能無法啓動。

5. 結論

在本文中,我們學習了 Spring 默認掃描哪些包以及如何自定義這些路徑。

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

發佈 評論

Some HTML is okay.