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里一切皆配置类

  1. 内置的那些bd会被排除
  2. 执行内置的BeanDefinitionRegistryPostProcessor之后的bd不算(也就是说ConfigurationClassPostProcessor之后的不算)

ComponentScanAnnotationParser#parse
useDefaultFilters 是否使用默认过滤器
Filters 两种过滤器

  1. include 引入
  2. exclude 排除

scanner.doScan->useDefaultFilters之后

  1. 把所谓的类(磁盘上的文件)都获取到
  2. 获取到这些类, 能不能变成bd(是不是符合规则)
    exclude(默认1个, 这个可以忽视)
    include

AbstractTypeHierarchyTraversingFilter#match()

  1. 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);
		}
	}
posted @ 2022-08-28 14:26  RichardHaha  阅读(80)  评论(0编辑  收藏  举报