1 Spring 内置的扫描器
使用XML 配置 Spring 组件扫描使用的是 component-scan
标签,其底层使用 ClassPathBeanDefinitionScanner
这个类完成扫描工作的。
到了 SpringBoot 这里,可以使用注解 @ComponentScan
注解配合 @Configuration
、@Service
、@Repository
和 @Controller
等注解使用,底层则使用了 ComponentScanAnnotationParser
解析器完成解析工作。
1.1 实现原理
ComponentScanAnnotationParser
解析器内部使用了 ClassPathBeanDefinitionScanner
扫描器.
ClassPathBeanDefinitionScanner
扫描器内部的处理过程整理如下:
遍历 basePackages,找出这个包下的所有的 class。找出之后封装成 Resource 接口集合,这个 Resource 接口是 Spring 对资源的封装,有 FileSystemResource、ClassPathResource、UrlResource
等实现。遍历找到的 Resource 集合,通过 includeFilters
和 excludeFilters
判断是否解析。这里的 includeFilters
和 excludeFilters
是TypeFilter
接口类型的集合,是 ClassPathBeanDefinitionScanner
内部的属性。
TypeFilter
接口是一个用于判断类型是否满足要求的类型过滤器。excludeFilters 中只要有一个TypeFilter满足条件,这个Resource就会被过滤。includeFilters 中只要有一个TypeFilter满足条件,这个Resource就会被保留,最后把保留的 Resource 封装成 ScannedGenericBeanDefinition
添加到 BeanDefinition
结果集中。
TypeFilter接口的定义:
public interface TypeFilter {
boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
throws IOException;
}
TypeFilter 常用实现:
- AnnotationTypeFilter:类是否有注解修饰
- RegexPatternTypeFilter:类名是否满足正则表达式。
ClassPathBeanDefinitionScanner
继承 ClassPathScanningCandidateComponentProvider
类
ClassPathScanningCandidateComponentProvider
内部的构造函数提供了一个 useDefaultFilters
参数,这个参数表示是否使用默认的TypeFilter,如果设置为true,会添加默认的TypeFilter:
public ClassPathScanningCandidateComponentProvider(boolean useDefaultFilters) {
this(useDefaultFilters, new StandardEnvironment());
}
// 默认 TypeFilter
protected void registerDefaultFilters() {
this.includeFilters.add(new AnnotationTypeFilter(Component.class));
ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
try {
this.includeFilters.add(new AnnotationTypeFilter(
((