zoukankan      html  css  js  c++  java
  • 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 {
    	//...
    }
    
  • 相关阅读:
    路由重分布(二)
    linux系统命令的收集 第一部分
    如何在VM软件中安装Linux系统
    Spring boot连接MongoDB集群
    jQuery中防止表单提交两次的方法
    Java中使用HTTP阻塞式调用服务器API
    本地项目初始化git推送到服务器
    前端页面调用Spring boot接口发生的跨域问题
    jQuery中异步问题:数据传递
    Git中修复bug
  • 原文地址:https://www.cnblogs.com/zongmin/p/13546176.html
Copyright © 2011-2022 走看看