交流
商城
MCN
登入
注册
首页
提问
分享
讨论
建议
公告
动态
发表新帖
发表新帖
spring核心第5 章:AutowireCandidateResolver
分享
未结
0
854
李延
LV6
2021-05-13
悬赏:20积分
# 作用 自动装配的用于获取候选者与判断符合要求的策略接口。主要功能有: 1、使用@Value时获取value值。 2、判断当前依赖是否符合@Quelifiers的条件 # 主要实现与调用 主要实现为ContextAnnotationAutowireCandidateResolver ## 调用  在DefaultListableBeanFactory中有成员变量为AutowireCandidateResolver  并且在doResolveDependency方法中调用了getSuggestedValue方法  在isAutowireCandidate方法中resolver.isAutowireCandidate。 关于这部分代码的调用逻辑在BeanFactory的resolveDependency中可以查看 ## 初始化 在使用springboot 时,使用的是AnnotationConfigApplicationContext上下文。而AnnotationConfigApplicationContext在初始化是创建的是ContextAnnotationAutowireCandidateResolver对象 # 继承关系  忽略掉Aware继承关系后,其继承关系就是一个笔直的关系。下面详细讲解 ## AutowireCandidateResolver 接口,定义了自动装配的候选集相关接口,主要有 1. isAutowireCandidate 判断当前bean定义是否符合候选集,在我们使用@Quelifiers注解时判断逻辑在这里。 2. isRequired 判断当前依赖是否为必须 3. hasQualifier 是否有筛选条件 4. getSuggestedValue 获取@Value的值 ## SimpleAutowireCandidateResolver 接口的简单实现,基本没有复杂逻辑,不做解析 ## GenericTypeAwareAutowireCandidateResolver ```java //TODO 待解析 ``` ## QualifierAnnotationAutowireCandidateResolver 关于注解的候选筛选 ### isAutowireCandidate ```java @Override public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) { //判断父类是否满足,关于类型的判断 boolean match = super.isAutowireCandidate(bdHolder, descriptor); if (match) { //关于限定符的判断 match = checkQualifiers(bdHolder, descriptor.getAnnotations()); if (match) { //方法注解判断判断 MethodParameter methodParam = descriptor.getMethodParameter(); if (methodParam != null) { Method method = methodParam.getMethod(); if (method == null || void.class == method.getReturnType()) { match = checkQualifiers(bdHolder, methodParam.getMethodAnnotations()); } } } } return match; } ``` 我们看到最后都是调用了checkQualifiers 方法进行判断 ```java protected boolean checkQualifiers(BeanDefinitionHolder bdHolder, Annotation[] annotationsToSearch) { if (ObjectUtils.isEmpty(annotationsToSearch)) { return true; } SimpleTypeConverter typeConverter = new SimpleTypeConverter(); for (Annotation annotation : annotationsToSearch) { Class<? extends Annotation> type = annotation.annotationType(); boolean checkMeta = true; boolean fallbackToMeta = false; //判断是否为qualifier注解 if (isQualifier(type)) { //判断是否符合qualifier注解要求 if (!checkQualifier(bdHolder, annotation, typeConverter)) { fallbackToMeta = true; } else { checkMeta = false; } } //判断注解上的注解情况 if (checkMeta) { boolean foundMeta = false; for (Annotation metaAnn : type.getAnnotations()) { Class<? extends Annotation> metaType = metaAnn.annotationType(); if (isQualifier(metaType)) { foundMeta = true; // Only accept fallback match if @Qualifier annotation has a value... // Otherwise it is just a marker for a custom qualifier annotation. if ((fallbackToMeta && ObjectUtils.isEmpty(AnnotationUtils.getValue(metaAnn))) || !checkQualifier(bdHolder, metaAnn, typeConverter)) { return false; } } } if (fallbackToMeta && !foundMeta) { return false; } } } return true; } ``` 其中我们看到核心代码为用isQualifier 方法判断是否为qualifier注解,并用checkQualifier 判断是否符合注解要求。继续跟进checkQualifier 方法 checkQualifier 代码有点多主要将一下大致逻辑: 1. 当注入字段与注入目标都有qualifier注解时,两者名称相同则可以注入对象。 2. 当注入目标没有qualifier注解时,注入字段的qualifier值与注入目标bean名称相同时可以主任。 ### getSuggestedValue 解决@Value值的获取 ```java @Override @Nullable public Object getSuggestedValue(DependencyDescriptor descriptor) { Object value = findValue(descriptor.getAnnotations()); if (value == null) { MethodParameter methodParam = descriptor.getMethodParameter(); if (methodParam != null) { value = findValue(methodParam.getMethodAnnotations()); } } return value; } ``` 我们可以看到最后使用findValue方法 ```java @Nullable protected Object findValue(Annotation[] annotationsToSearch) { if (annotationsToSearch.length > 0) { // qualifier annotations have to be local AnnotationAttributes attr = AnnotatedElementUtils.getMergedAnnotationAttributes( AnnotatedElementUtils.forAnnotations(annotationsToSearch), this.valueAnnotationType); if (attr != null) { return extractValue(attr); } } return null; } ``` 其中成员变量:valueAnnotationType的值时@Value。当前方法就是获取@Value的值。
回帖
消灭零回复
提交回复
热议榜
java 相关知识分享
8
好的程序员与不好的程序员
6
写给工程师的十条精进原则
5
spring boot以jar包运行配置的logback日志文件没生成
5
一步一步分析SpringBoot启动源码(一)
5
MockMvc测试
5
【吐槽向】是不是有个吐槽的板块比较好玩
4
logstash jdbc同步mysql多表数据到elasticsearch
3
IntelliJ IDEA 优质License Server
3
.gitignore忽略规则
3
SpringBoot启动源码分析
3
一步一步分析SpringBoot启动源码(三)
3
2
一步一步分析SpringBoot启动源码(二)
2
积分不够将无法发表新帖
2
官方产品
Meta-Boot - 基于MCN
MCN - 快速构建SpringBoot应用
微信扫码关注公众号