component-scan 標簽的 use-default-filters 屬性用法


在進行 SSM 整合時,常常使用<component-scan>標簽進行注解掃描,而該標簽中有個常常被忽略的屬性 use-default-filters。該屬性是個特別重要的屬性,本文將會對該屬性進行介紹。

原理分析

在進行 SSM 整合時,一般都會將 Spring 和 SpringMVC 的配置分別寫在兩個配置文件中。Spring 配置文件一般配置的是非 Web 組件的 bean,比如 DataSource、Service;而 SpringMVC 配置文件一般配置的是 Web 組件的 bean,比如控制器、視圖解析器。所以,Spring 和 SpringMVC 配置文件的注解掃描的包路徑是不同的。

☕️ Spring 配置文件中的注解掃描

<!-- 配置 IoC 容器注解掃描的包路徑 -->
<context:component-scan base-package="com.example">
    <!-- 制定掃包規則,不掃描 @Controller 注解修飾的 Java 類,其它還是要掃描 -->
    <context:exclude-filter type="annotation"
                            expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

☕️ SpringMVC 配置文件中的注解掃描

<!-- 配置 IoC 容器的注解掃描的包路徑 -->
<context:component-scan base-package="com.example" use-default-filters="false">
    <!-- 制定掃包規則,只掃描使用 @Controller 注解修飾的 Java 類 -->
    <context:include-filter type="annotation"
                            expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

從上面可以發現,使用<exclude-filter>標簽時,沒有將 use-default-filters 屬性設置為 false;而在使用<include-filter>標簽時,將 use-default-filters 屬性設置為 false。這是為什么?

這一切都要歸結為 use-default-filters 屬性的作用,該屬性的默認值為 true,意為使用默認的 Filter 進行注解掃描,而該 Filter 會掃描所有 @Component 注解及其子注解。我們查看源碼:

protected void registerDefaultFilters() {
    // 將 @Component 注解添加進 Filter 掃描中
    this.includeFilters.add(new AnnotationTypeFilter(Component.class));
    ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();

    try {
        this.includeFilters.add(new AnnotationTypeFilter(ClassUtils.forName("javax.annotation.ManagedBean", cl), false));
        this.logger.trace("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
    } catch (ClassNotFoundException var4) {
    }

    try {
        this.includeFilters.add(new AnnotationTypeFilter(ClassUtils.forName("javax.inject.Named", cl), false));
        this.logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
    } catch (ClassNotFoundException var3) {
    }
}

因此默認的 filter 會掃描所有 @Component 注解修飾的 Java 類,而 @Controller、@Service、@Repository 甚至是 @Configuration 注解都是 @Componet 的衍生注解,所以也會被掃描到。因此,最簡單的注解掃描配置就是只配置包路徑,而 use-default-filters 屬性不需要配置,其值默認為 true:

<!-- 配置 IoC 容器的注解掃描的包路徑 -->
<context:component-scan base-package="com.example"/>

⭐️ 現在回過頭查看 Spring 配置文件中的配置:

<!-- 配置 IoC 容器的注解掃描的包路徑 -->
<context:component-scan base-package="com.example">
    <!-- 制定掃包規則,不掃描 @Controller 注解修飾的 Java 類,其它還是要掃描 -->
    <context:exclude-filter type="annotation"
                            expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

use-default-filters 默認值為 true,默認會掃描 @Component、@Controller、@Service、@Repository 甚至是 @Configuration 注解修飾的 Java 類;而<exclude-filter>標簽指定將 @Controller 注解排除,所以最后只會掃描 @Component、@Service、@Repository 和 @Configuration 注解修飾的 Java 類。

⭐️ 查看 SpringMVC 配置文件中的配置

<!-- 配置 IoC 容器的注解掃描的包路徑 -->
<context:component-scan base-package="com.example" use-default-filters="false">
    <!-- 制定掃包規則,只掃描使用 @Controller 注解修飾的 Java 類 -->
    <context:include-filter type="annotation"
                            expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

use-default-filters 屬性值設置為 false,默認的 filters 關閉,意味着不會進行任何掃描;而<include-filter>標簽指定掃描 @Controller 注解,所以最終只會掃描 @Controller 注解修飾的 Java 類。


注解方式使用

✏️ Spring 配置類中的注解掃描配置

@Configuration
@ComponentScan(value = "com.example",  // 配置 IoC 容器注解掃描的包路徑
        // 制定掃包規則,不掃描 @Controller 注解修飾的 Java 類,其它還是要掃描
        excludeFilters = @Filter(type = FilterType.ANNOTATION, 
                                 value = Controller.class))
public class SpringConfig {
    //...
}

✏️ SpringMVC 配置類中的注解掃描配置

@Configuration
@ComponentScan(value = "com.example",  // 配置 IoC 容器注解掃描的包路徑
        useDefaultFilters = false,     // 關閉默認的注解掃描的 Filter
        // 制定掃包規則,只掃描使用 @Controller 注解修飾的 Java 類
        includeFilters = @Filter(type = FilterType.ANNOTATION, 
                                 value = Controller.class)
)
public class SpringMvcConfig {
	//...
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM