02、Spring常用注解一@ComponentScan

1. @ComponentScan 扫描规则

1.1 指定要扫描的包

  • 1 新建配置类Cap2MainConfig,
@ComponentScan(value = "com.zz.cap2")
public class Cap2MainConfig {
}

@ComponentScan(value = “com.zz.cap2”)表示扫描此目录下的包

  • 2 在com.zz.cap2目录下新建要扫描的类
    在这里插入图片描述

OrderController

@Controller
public class OrderController {
}

OrderService

@Service
public class OrderService {
}

OrderDao

@Repository
public class OrderDao {
}

  • 3 新建测试类Cap2Test
public class Cap2Test {
    @Test
    public void test1() {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Cap2MainConfig.class);
        //从容器获取bean定义的名称
        String[] names = context.getBeanDefinitionNames();
        for( String name : names) {
            System.out.println(name);
        }
    }
}

结果:
在这里插入图片描述

使用 ApplicationContext 的 getBeanDefinitionNames() 方法获取已经注册到容器中的 bean 的名称。

1.2 定制包扫描的过滤规则

1.2.1 excludeFilters 和 includeFilters 的使用

1.使用 excludeFilters 来按照规则排除某些包的扫描

修改配置类:

@ComponentScan(value = "com.zz.cap2", excludeFilters = {@Filter(type = FilterType.ANNOTATION, value = Controller.class)})
public class Cap2MainConfig {
}

excludeFilters 的参数是一个 Filter[] 数组,然后指定 FilterType 的类型为 ANNOTATION,也就是通过注解来过滤,最后的 value 则是Controller 注解类。配置之后,在 spring 扫描的时候,就会跳过 com.zz.cap2 包下,所有被 @Controller 注解标注的类。

结果:
在这里插入图片描述
orderController没有打印出来,排除成功

2.使用 includeFilters 来按照规则只包含某些包的扫描

修改配置类:

@ComponentScan(value = "com.zz.cap2", includeFilters = {@Filter(type = FilterType.ANNOTATION, value = Controller.class)})
public class Cap2MainConfig {
}

在这里插入图片描述
配置里面,应该是只包含 @Controller 注解的类才会被注册到容器中,为什么 @Service 注解的类也被注册了呢?这里涉及到 @ComponentScan 的一个 useDefaultFilters 属性的用法,该属性默认值为 true,也就是说 spring 默认会自动发现被 @Component、@Repository、@Service 和 @Controller 标注的类,并注册进容器中。要达到只包含某些包的扫描效果,就必须将这个默认行为给禁用掉(在 @ComponentScan 中将 useDefaultFilters 设为 false 即可)。

设置useDefaultFilters 为false

@ComponentScan(value = "com.zz.cap2", includeFilters = {@Filter(type = FilterType.ANNOTATION, value = Controller.class)}, useDefaultFilters = false)
public class Cap2MainConfig {
}

结果
在这里插入图片描述

1.2.2 添加自定义过滤规则

在前面使用过 @Filter 注解,里面的 type 属性是一个 FilterType 的枚举类型:

public enum FilterType {

    ANNOTATION,            //按照注解过滤
    ASSIGNABLE_TYPE,       //按照给定的类型
    ASPECTJ,               //使用ASPECTJ表达式
    REGEX,                 //正则
    CUSTOM                 //自定义规则

}


使用 CUSTOM 类型,就可以实现自定义过滤规则。

  • 首先创建一个实现 TypeFilter 接口的 CustomTypeFilter 类,并实现其 match 方法。
public class CustomTypeFilter implements TypeFilter {
    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        // 获取当前扫描到的类的注解元数据
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        // 获取当前扫描到的类的元数据
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        // 获取当前扫描到的类的资源信息
        Resource resource = metadataReader.getResource();

        if (classMetadata.getClassName().contains("vice")) {
            return true;
        }

        return false;
    }
}

这里简单对扫描到的类名进行判断,如果类名包含”vice“的就符合条件,也就会注入到容器中。

  • 对 Cap2MainConfig进行修改,指定过滤类型为 Custom 类型,并指定 value 为 CustomTypeFilter.class。
@ComponentScan(value = "com.zz.cap2", includeFilters = {@Filter(type = FilterType.CUSTOM, value = CustomTypeFilter.class)}, useDefaultFilters = false)
public class Cap2MainConfig {
}

运行结果:
在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章