同步操作将从 huifer/Code-Analysis 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
org.springframework.beans.factory.annotation.QualifierAnnotationAutowireCandidateResolver
关于QualifierAnnotationAutowireCandidateResolver
我们首先对其中的两个成员变量进行分析
public class QualifierAnnotationAutowireCandidateResolver extends GenericTypeAwareAutowireCandidateResolver {
/**
* Qualifier 相关的注解类型
*/
private final Set<Class<? extends Annotation>> qualifierTypes = new LinkedHashSet<>(2);
/**
* value 注解.class
*/
private Class<? extends Annotation> valueAnnotationType = Value.class;
}
valueAnnotationType
就是注解 Value 的class
还有一个是存储Qualifier
相关的set集合. 存储 Class
从整个类的阅读上目前可以知道存储了
1. org.springframework.beans.factory.annotation.Qualifier
2. javax.inject.Qualifier在了解成员变量后接下来进行方法分析
org.springframework.beans.factory.annotation.QualifierAnnotationAutowireCandidateResolver.isAutowireCandidate
@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;
}
在这个方法上主要围绕注解进行展开. 注解的获取方式成为了一个重要的方法, 下面我们看一下在这段方法(isAutowireCandidate
)中有那些获取方式
1. DependencyDescriptor
中的属性. 依赖描述的注解属性
2. 方法参数的注解
checkQualifiers
方法. 我们将目光着重放在checkQualifiers
身上org.springframework.beans.factory.annotation.QualifierAnnotationAutowireCandidateResolver.checkQualifiers
/**
* Match the given qualifier annotations against the candidate bean definition.
*/
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;
// 注解类型是否在 qualifierTypes 中
if (isQualifier(type)) {
// 验证是否匹配
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.
// StringUtils.isEmpty(AnnotationUtils.getValue(metaAnn)) 存在数据: Qualifier value 存在数据
if ((fallbackToMeta && StringUtils.isEmpty(AnnotationUtils.getValue(metaAnn))) ||
!checkQualifier(bdHolder, metaAnn, typeConverter)) {
return false;
}
}
}
if (fallbackToMeta && !foundMeta) {
return false;
}
}
}
return true;
}
两层循环.
第一层注解是当前类上的.
第二层是注解上的注解
在这一方法中更多的信息在checkQualifier
方法中
org.springframework.beans.factory.annotation.QualifierAnnotationAutowireCandidateResolver#checkQualifier
先阅读第一部分代码
// 第一部分
// 获取注解类型
Class<? extends Annotation> type = annotation.annotationType();
// 提取 bean 定义
RootBeanDefinition bd = (RootBeanDefinition) bdHolder.getBeanDefinition();
// 获取 AutowireCandidateQualifier . 通过类名的方式获取
// 从容器(qualifiers)中获取
AutowireCandidateQualifier qualifier = bd.getQualifier(type.getName());
if (qualifier == null) {
// 没有获取到的话 通过类的短名字获取
qualifier = bd.getQualifier(ClassUtils.getShortName(type));
}
在第一部分代码中的所有操作都是为了获取AutowireCandidateQualifier
在获取的时候采用两种方式
这里衍生出一个问题: 在已知长短类名的情况下从哪里获取?
这里涉及到下面这个对象(AbstractBeanDefinition
属性)
private final Map<String, AutowireCandidateQualifier> qualifiers = new LinkedHashMap<>();
第一部分结束进入第二部分代码分析
第二部分代码相关内容是围绕 qualifier 在上述搜索模式下搜索不到的情况
第二部分代码分上下两段阅读.
// First, check annotation on qualified element, if any
// 提取注解 qualified (这里不一定是 qualified 注解, 也可能是 type 类型, type 类型即 入参注解)
Annotation targetAnnotation = getQualifiedElementAnnotation(bd, type);
// Then, check annotation on factory method, if applicable
if (targetAnnotation == null) {
// 工厂方法的注解获取
targetAnnotation = getFactoryMethodAnnotation(bd, type);
}
if (targetAnnotation == null) {
// 依赖描述的解析
RootBeanDefinition dbd = getResolvedDecoratedDefinition(bd);
if (dbd != null) {
// 工厂方法的注解获取
targetAnnotation = getFactoryMethodAnnotation(dbd, type);
}
}
上半部分代码围绕targetAnnotation
的获取来编写.
在这里有2种方式来进行获取
getQualifiedElementAnnotation
getFactoryMethodAnnotation
下面先来看 getQualifiedElementAnnotation
方法
org.springframework.beans.factory.annotation.QualifierAnnotationAutowireCandidateResolver#getQualifiedElementAnnotation
@Nullable
protected Annotation getQualifiedElementAnnotation(RootBeanDefinition bd, Class<? extends Annotation> type) {
AnnotatedElement qualifiedElement = bd.getQualifiedElement();
return (qualifiedElement != null ? AnnotationUtils.getAnnotation(qualifiedElement, type) : null);
}
org.springframework.beans.factory.annotation.QualifierAnnotationAutowireCandidateResolver#getFactoryMethodAnnotation
@Nullable
protected Annotation getFactoryMethodAnnotation(RootBeanDefinition bd, Class<? extends Annotation> type) {
Method resolvedFactoryMethod = bd.getResolvedFactoryMethod();
return (resolvedFactoryMethod != null ? AnnotationUtils.getAnnotation(resolvedFactoryMethod, type) : null);
}
在这里我们就两个方法一起看了. 两者的目的都是获取 type 对应的注解
getQualifiedElementAnnotation
从 BeanDefinition 的 qualifiedElement
属性中获取
getFactoryMethodAnnotation
从 方法的注解中获取
第二部分的上篇还有getResolvedDecoratedDefinition
方法. 主要作用是将两个bean合并
两个bean分别是
接下来对第二部分的下篇代码进行分析
if (targetAnnotation == null) {
// Look for matching annotation on the target class
if (getBeanFactory() != null) {
try {
// 查询依赖的bean类型
Class<?> beanType = getBeanFactory().getType(bdHolder.getBeanName());
if (beanType != null) {
targetAnnotation = AnnotationUtils.getAnnotation(ClassUtils.getUserClass(beanType), type);
}
}
catch (NoSuchBeanDefinitionException ex) {
// Not the usual case - simply forget about the type check...
}
}
if (targetAnnotation == null && bd.hasBeanClass()) {
targetAnnotation = AnnotationUtils.getAnnotation(ClassUtils.getUserClass(bd.getBeanClass()), type);
}
}
if (targetAnnotation != null && targetAnnotation.equals(annotation)) {
return true;
}
第二部分下篇通过 BeanFactory
找到 beanName
对应的类型,通过类型去搜索注解(type
)
目标还是targetAnnotation
, 求其真正的值.
最后判断是否类型相同
if (targetAnnotation != null && targetAnnotation.equals(annotation)) {
return true;
}
第二部分上下两段阅读分析完成. 下面进行checkQualifier
第三部分代码分析
// 第三部分
// 获取注解的属性列表
Map<String, Object> attributes = AnnotationUtils.getAnnotationAttributes(annotation);
if (attributes.isEmpty() && qualifier == null) {
// If no attributes, the qualifier must be present
return false;
}
for (Map.Entry<String, Object> entry : attributes.entrySet()) {
String attributeName = entry.getKey();
Object expectedValue = entry.getValue();
Object actualValue = null;
// Check qualifier first
if (qualifier != null) {
// 获取属性
actualValue = qualifier.getAttribute(attributeName);
}
if (actualValue == null) {
// Fall back on bean definition attribute
// bean定义中获取属性
actualValue = bd.getAttribute(attributeName);
}
if (actualValue == null && attributeName.equals(AutowireCandidateQualifier.VALUE_KEY) &&
expectedValue instanceof String && bdHolder.matchesName((String) expectedValue)) {
// Fall back on bean name (or alias) match
continue;
}
if (actualValue == null && qualifier != null) {
// Fall back on default, but only if the qualifier is present
// 默认值获取
actualValue = AnnotationUtils.getDefaultValue(annotation, attributeName);
}
if (actualValue != null) {
actualValue = typeConverter.convertIfNecessary(actualValue, expectedValue.getClass());
}
if (!expectedValue.equals(actualValue)) {
return false;
}
}
return true;
第三部分只做一件事 expectedValue
和 actualValue
是否相同
在代码中有actualValue
的不同的确认方式(取值方式),下面来说一说获取方式
qualifier
中提取属性
qualifier.getAttribute(attributeName)
beanDefinition
中提取属性
bd.getAttribute(attributeName)
从注解中获取
AnnotationUtils.getDefaultValue(annotation, attributeName)
从类型转换器中转换后获取
typeConverter.convertIfNecessary(actualValue, expectedValue.getClass())
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。