【Spring注解】@ComponentScan之includeFilters和excludeFilters
源码:https://github.com/nieandsun/spring-study
1. 概念
1.1 先看一段代码
1.2 type—FilterType
FilterType为一个枚举类,总共有5个值,也就是说type总共有5个可选值
public enum FilterType {
ANNOTATION,//按照注解方式
ASSIGNABLE_TYPE,//按照指定类型的方式
ASPECTJ,//使用ASPECTJ表达式的方式-------没用过,不演示
REGEX,//利用正则表达式进行指定-----------没用过,不演示
CUSTOM//自己实现TypeFilter接口进行自定义规则(如下面的代码)
}
1.3 实现TypeFilter接口—自定义规则
下面的代码
- 如果放在excludeFilters里,会过滤掉含有Buy字符的类-----即不扫描
- 如果放在includeFilters里,会扫描含有Buy字符的类---------扫描
package com.nrsc.springstudy.c1_componentscan1.study2.config;
import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;
import java.io.IOException;
public class NrscTypeFilter implements TypeFilter {
private ClassMetadata classMetadata;
/**
* MetadataReader:读取到当前正在扫描类的信息
* MetadataReaderFactory:可以获取到其他任何类信息
*/
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
//获取当前类注解的信息
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
//获取当前正在扫描的类信息
classMetadata = metadataReader.getClassMetadata();
//获取当前类资源(类的路径)
Resource resource = metadataReader.getResource();
String className = classMetadata.getClassName();
System.out.println("----->" + className);
//当类包含Buy字符, 则匹配成功,返回true
//excludeFilters返回true---->会被过滤掉
//includeFilters返回true---->会通过
if (className.contains("Buy")) {
return true;
}
return false;
}
}
2 .代码演示—以excludeFilters为例
Config1配置类的代码如下图所示,代码中的NrscTypeFilter 即为上面的代码.
按照代码以及项目的目录结构可以猜出,config1_test中的类只有OrderController1能被注册到spring容器中.
3.includeFilters&useDefaultFilters = false
3.1 为何
- 如下图,当使用includeFilters想只扫描含有@Service注解的类时,必须要加上useDefaultFilters = false
先验证一下效果
再简单说下原因:
其实@Component,@Controller,@Service和@Repository三者功能相同,后三个注解是为了对应后端代码的三层结构由第一个注解"复制"而来的.查看源码可以发现,后三个注解上面都有一个@Component.
- 也就是说@Controller,@Service和@Repository除了是它们自己,也是一个@Component
- 在进行includeFilters过滤时,如果useDefaultFilters =true,它会默认把所有包含@Component注解的类都进行扫描
因此只有加上useDefaultFilters=false才能得到正确的结果
3.2 多说几句
真的懂了上面我说的原因,你肯定就不会为使用下面的配置类,能扫描到所有含有@Component,@Controller,@Service和@Repository注解的类而疑惑了.
@Configuration
@ComponentScan(value = "com.nrsc.springstudy.c1_componentscan1.study2.config2_test",
includeFilters = {
@Filter(type = FilterType.ANNOTATION, classes = {Component.class})},
useDefaultFilters = false)
public class Config3 {