zoukankan      html  css  js  c++  java
  • (一)IOC 容器:【2】@ComponentScan 自动扫描组件&指定扫描规则

    注解

    @ComponentScan 通过此注解来设置包,类的扫描规则。
    

      

    一、配置文件开发

       在 Spring 配置文件中使用 <context:component-scan> 标签来设置包的扫描规则。

      

    二、注解开发

      在原来的配置类上面,可以添加 @ComponentScan 注解来添加类的扫描规则。

      @ComponentScan 注解中使用 value属性来指定要扫描的包

    @Configuration
    @ComponentScan(value = "com.njf")//value 指定要扫描的包
    public class MainConfig {
    
        /**
         * 使用 @Bean 注册一个 bean 组件,bean 类型是返回值的类型,id 默认是方法名即(person)
         * 修改 id 名
         *  1)修改方法名;
         *  2)注解中 value 值即 bean 的 id
         * @return
         */
        @Bean(name = "Person")
        public Person person01() {
            return new Person("李四", 20);
        }
    }

    三、@ComponentScan 常用属性方法

      1、指定扫描的包

        value() 和 basePackages() 可以指定扫描要的包;

        

         这两个方法都是一样,可以使用 value 或者 basePackages() 来指定扫描的包;(可以使用表达式)

      2、排除指定组件

    excludeFilters = Filter[]   指定扫描的时候按照指定规则排除那些组件
    

        示例:按照注解规则排除指定的组件

    @ComponentScan(value = "com.njf", excludeFilters = {
            @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class})
    })

      3、包含指定组件

    includeFilters = Filter[]   指定扫描的时候按照指定只包含那些组件(把useDefaultFilters设置为false)

      示例:按照指定规则扫描对应的组件

    @ComponentScan(value = "com.njf", includeFilters = {
            @ComponentScan.Filter(type=FilterType.ANNOTATION, classes=  {Controller.class}),          //使用注解
            @ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE, classes = {BookService.class})   //使用类的类型
    }, useDefaultFilters = false)

      注意:默认是扫描所有的组件,一定要禁用掉,然后按照指定的规则扫描,一定要设置 useDefaultFilters 设置为 false,即不扫描全部的,只扫描指定的类

    四、自定义扫描规则

      在上面的扫描规则中,都是通过添加 Filter 来指定扫描规则的。

      在 @ComponentScan.Filter 注解中有一个 type() 属性方法,指定了通过哪一种规则来进行扫描的。

      源码:

        @Retention(RetentionPolicy.RUNTIME)
        @Target({})
        @interface Filter {
    
            FilterType type() default FilterType.ANNOTATION;
    
            @AliasFor("classes")
            Class<?>[] value() default {};
    
            @AliasFor("value")
            Class<?>[] classes() default {};
    
            String[] pattern() default {};
    
        }

      默认使用的按照注解的类型来扫描的。

      FilterType 枚举类中定义了如下几种方式的扫描规则:

    FilterType.ANNOTATION       按照注解的类型
    FilterType.ASSIGNABLE_TYPE  按照给定的类型
    FilterType.ASPECTJ          按照aspectj 表达式
    FilterType.REGEX            按照正则表达式来指定
    FilterType.CUSTOM           使用自定义规则
    

      

      可以看到我们可以自定义Filter来进行包的扫描规则。

       对于自定义Filter,需要是 TypeFilter 的实现类。

       创建自定义的 Filter,定义一个普通类,实现 TypeFilter:

    public class MyTypeFilter implements TypeFilter {
    
        /*
         * @param metadataReader : 读取到的当前正在扫描的类的信息
         * @param metadataReaderFactory : 可以获取到其他任何类信息
         */
        @Override
        public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
            //获取当前类注解的信息
            AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
    
            //获取当前正在扫描的类的类信息
            ClassMetadata classMetadata = metadataReader.getClassMetadata();
    
            //获取当前类资源(类的路径)
            Resource resource = metadataReader.getResource();
    
            String className = classMetadata.getClassName();
            System.out.println("--->" + className);
    
            if (className.contains("er")) {  //表示当扫描的类名中有er时,就会包含该类
                return true;
            }
            return false;
        }
    }

      使用自定义的过滤规则进行扫描:

    @ComponentScan(value = "com.njf", includeFilters = {
            @ComponentScan.Filter(type=FilterType.ANNOTATION, classes=  {Controller.class}),          //使用注解
            @ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE, classes = {BookService.class}),   //使用类的类型
            @ComponentScan.Filter(type=FilterType.CUSTOM, classes = {MyTypeFilter.class})            //使用自定义规则
    }, useDefaultFilters = false)

    五、其他

      1、@ComponentScan 重复使用

        在Spring的高版本(4.0以上)声明为了重复注解:

        

         可以在配置类上写多个 @ComponentScan 扫描规则:

    @Configuration
    @ComponentScan(value = "com.njf", excludeFilters = {
            @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class})
    })
    @ComponentScan(value = "com.njf", includeFilters = {
            @ComponentScan.Filter(type=FilterType.ANNOTATION, classes=  {Controller.class}),          //使用注解
            @ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE, classes = {BookService.class}),   //使用类的类型
            @ComponentScan.Filter(type=FilterType.CUSTOM, classes = {MyTypeFilter.class})            //使用自定义规则
    }, useDefaultFilters = false)
    public class MainConfig {
    
        /**
         * 使用 @Bean 注册一个 bean 组件,bean 类型是返回值的类型,id 默认是方法名即(person)
         * 修改 id 名
         *  1)修改方法名;
         *  2)注解中 value 值即 bean 的 id
         * @return
         */
        @Bean(name = "Person")
        public Person person01() {
            return new Person("李四", 20);
        }
    }

        如果是 JDK8,可以像上面写多个包扫描器 @ComponentScan;

        如果不是 JDK8,可以使用下面的 @ComponentScans 指定多个包扫描规则;  

      2、使用@ComponentScans 

        使用 @ComponentScans 注解,可以在 value 数组里面放多个 @ComponentScan;

        @ComponentScans 和 @ComponentScan 注解不可以同时使用!

    @Configuration
    @ComponentScans(
            value = {
                    @ComponentScan(value = "com.njf", excludeFilters = {
                            @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class})
                    }),
                    @ComponentScan(value = "com.njf", excludeFilters = {
                            @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Service.class})
                    })
            }
    )
    public class MainConfig {
    
        /**
         * 使用 @Bean 注册一个 bean 组件,bean 类型是返回值的类型,id 默认是方法名即(person)
         * 修改 id 名
         *  1)修改方法名;
         *  2)注解中 value 值即 bean 的 id
         * @return
         */
        @Bean(name = "Person")
        public Person person01() {
            return new Person("李四", 20);
        }
    }
      结论:如果有多个@ComponentScan时,各个@ComponentScan扫描到的类的交集都会被注册到spring容器中。
     
     
  • 相关阅读:
    typescript
    js-解决安卓手机软键盘弹出后,固定定位布局被顶上移问题
    vue
    js
    Object.assgin基本知识与相关深浅拷贝
    js-工具方法(持续更新)
    vue
    vue
    git
    css
  • 原文地址:https://www.cnblogs.com/niujifei/p/15543072.html
Copyright © 2011-2022 走看看