随笔 - 1162  文章 - 0  评论 - 16  阅读 - 59万 

注解

@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 容器中。

posted on   格物致知_Tony  阅读(267)  评论(0编辑  收藏  举报
编辑推荐:
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
历史上的今天:
2019-11-12 Float型 与 Double型数据的存储方式
点击右上角即可分享
微信分享提示

目录导航