component-scan 标签的 use-default-filters 属性用法


在进行 SSM 整合时,常常使用标签进行注解扫描,而该标签中有个常常被忽略的属性 use-default-filters。该属性是个特别重要的属性,本文将会对该属性进行介绍。

原理分析

在进行 SSM 整合时,一般都会将 Spring 和 SpringMVC 的配置分别写在两个配置文件中。Spring 配置文件一般配置的是非 Web 组件的 bean,比如 DataSource、Service;而 SpringMVC 配置文件一般配置的是 Web 组件的 bean,比如控制器、视图解析器。所以,Spring 和 SpringMVC 配置文件的注解扫描的包路径是不同的。

?? Spring 配置文件中的注解扫描



    
    

?? SpringMVC 配置文件中的注解扫描



    
    

从上面可以发现,使用标签时,没有将 use-default-filters 属性设置为 false;而在使用标签时,将 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:



?? 现在回过头查看 Spring 配置文件中的配置:



    
    

use-default-filters 默认值为 true,默认会扫描 @Component、@Controller、@Service、@Repository 甚至是 @Configuration 注解修饰的 Java 类;而标签指定将 @Controller 注解排除,所以最后只会扫描 @Component、@Service、@Repository 和 @Configuration 注解修饰的 Java 类。

?? 查看 SpringMVC 配置文件中的配置



    
    

use-default-filters 属性值设置为 false,默认的 filters 关闭,意味着不会进行任何扫描;而标签指定扫描 @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 {
	//...
}