Spring5.2.x-06-Spring扫描原理
在 ConfigurationClassPostProcessor 内部完成扫描
在扫描的时候, 为什么要用asm, 如果直接用类, 可能会把 static 里的直接执行了, spring尽量做到不直接影响用户(比如这是lazy的bean, 扫描出来又不是需要实例化bean, 怎么能执行static, 语义上说不通)
内部分为两个扫描成
scanner1(api调用, 定制化程度小), 手动调用 sacn -> 最终调用 doScan 方法
scanner2(通常是这个, 扫描注解, 定制化程度大), 通过refresh, 执行到 invokeBeanFactoryPostProcessors, 执行 ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry, 判断 @ComponentSacn 注解, 没有就不执行, 有继续执行扫描 -> 最终调用 doScan 方法
简单区别, scanner1 可以定制, 如名字生成策略, 或满足某种条件后执行扫描(动态编程), scanner2不行
spring里一切皆配置类
- 内置的那些bd会被排除
- 执行内置的BeanDefinitionRegistryPostProcessor之后的bd不算(也就是说ConfigurationClassPostProcessor之后的不算)
ComponentScanAnnotationParser#parse
useDefaultFilters 是否使用默认过滤器
Filters 两种过滤器
- include 引入
- exclude 排除
scanner.doScan->useDefaultFilters之后
- 把所谓的类(磁盘上的文件)都获取到
- 获取到这些类, 能不能变成bd(是不是符合规则)
exclude(默认1个, 这个可以忽视)
include
AbstractTypeHierarchyTraversingFilter#match()
- matchShelf 默认返回false, 匹配自身信息
遍历excludeFilters
遍历includeFilters
在实例化扫描器的时候, registerDefaultFilters添加了3个includeFilter,
for (TypeFilter tf : this.includeFilters) {
// 1. default: tf = new AnnotationTypeFilter(Component.class)
// AnnotationTypeFilter 重写了 matchSelf 方法, 判断是否为 @Componet
// 2. default: tf = new AnnotationTypeFilter(
// ((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl))
// AnnotationTypeFilter 重写了 matchSelf 方法, 判断是否为 @ManagedBean
// 3. default: tf = new AnnotationTypeFilter(
// ((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl))
// AnnotationTypeFilter 重写了 matchSelf 方法, 判断是否为 @Named
// 4. config 里注解导入: tf = new AssignableTypeFilter(filterClass)
// AssignableTypeFilter 重写了 matchClassName 方法, 判断 className 是否为构造方法参数class
if (tf.match(metadataReader, getMetadataReaderFactory())) {
return isConditionMatch(metadataReader);
}
}