spring注解中动态传值_Spring 中注解扫描

“在工作中我们可能需要在程序启动的时候扫描特定的注解,做一些初始化或预加载的工作,Spring 中各种配置类、Bean的加载都离不开注解类的解析。本文带你分析此类的工作原理”

Spring中注解扫描是以 ClassPathScanningCandidateComponentProvider 类为基础,本文带你分析此类的工作原理。

首先我们看构造函数,useDefaultFilters 一般需要扫描自定义的包需要传 false,然后创建一个 StandardEnvironment,这个我们用不上可以直接忽略。

public ClassPathScanningCandidateComponentProvider(boolean useDefaultFilters) {
    this(useDefaultFilters, new StandardEnvironment());
  }

然后下面这两个接口可以添加 TypeFilter,通过 TypeFilter 的 match 方法来确定扫描的类是否符合条件。

  public void addIncludeFilter(TypeFilter includeFilter) {
    this.includeFilters.add(includeFilter);
  }
  public void addExcludeFilter(TypeFilter excludeFilter) {
    this.excludeFilters.add(0, excludeFilter);
  }

比较常用的就是 AnnotationTypeFilter,里面包含一个属性 Class 即你需要匹配的注解类。AnnotationTypeFilter 继承 AbstractTypeHierarchyTraversingFilter,看名字中 Hierarchy 我们知道,此抽象类实现了层次的查找,不仅会查找当前类,还会查找他的父类或接口。

9b0bf3a8ef5a300e462f94e2cbc5f34e.png

AnnotationTypeFilter 只能匹配类上的注解,比如你需要匹配方法上的注解,你可以继承 AbstractTypeHierarchyTraversingFilter 来自定义自己的匹配规则。

然后调用ClassPathScanningCandidateComponentProvider.findCandidateComponents 方法开始扫包。调用流程如下:

f494891fdd15ddbdb7b6155d29e84964.png

①:入参是你需要扫描的包,例如:com.codermeng

②:会将上一步入参 basePackage 转换成带协议前缀和类通配符的路径,例如:classpath*:com/codermeng/**/*.class。getResources 返回一个 List 包含所有符合条件的 class 文件相对路径,例如:/Users/xxx/target/test-classes/com/codermeng/ClassScanTest.class。

③:这一步就会遍历 Resource List ,对每个 Resource 进行字节码解析。解析完之后会根据配置的 excludeFilterincludeFilter 对每个 class 的进行过滤,符合条件的会封装成 BeanDefinition 返回。

ClassReader 进行字节码解析完会返回一个 AnnotationMetadata,里面有方法判断注解是否在类上存在,是否在方法上存在,此接口常用方法摘抄如下:

// 判断类上是否存在此名称的 Annotation 
boolean hasAnnotation(String annotationName);

// 判断类上是否存在此名称的 MetaAnnotation
boolean hasMetaAnnotation(String metaAnnotationName);

// 判断类的方法上是否存在此名称的 Annotation
boolean hasAnnotatedMethods(String annotationName);

// 获取包含此 Annotation 的方法
Set<MethodMetadata> getAnnotatedMethods(String annotationName);

微信搜索 CoderMeng 关注获取更多干货文章

大家觉得写的不错欢迎点赞评论分享支持。

推荐阅读

CoderMeng:JVM锁粗化和循环​zhuanlan.zhihu.com
CoderMeng:Google Protocol Buffers 序列化原理​zhuanlan.zhihu.com
CoderMeng:Java网络学习必备:I/O模型和Reactor模式​zhuanlan.zhihu.com
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值