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 {
	//...
}
posted @ 2020-08-22 16:33  呵呵233  阅读(854)  评论(0编辑  收藏  举报