checkQualifier检查要候选bean定义是否有这个注解
这个方法其实就是检查候选的bean定义里有没有相关Qualifier
注解,先检查下bean
定义有没有添加type
类型的全限定类型和短类名的AutowireCandidateQualifier
对象,如果没有的话就看有没有设置type
类型的AnnotatedElement
对象,还没有的话就检查bean定义的工厂方法上有没有这个type
注解,我们这个刚好在这上面,再没有的话就从bean
装饰的定义中找注解,最后为空的话就从bean
定义的目标类上去找。如果AutowireCandidateQualifier
存在的话,就获取他的属性和type
限定注解上的属性做匹配。最后返回是否找到或者是否匹配上。
protected boolean checkQualifier(
BeanDefinitionHolder bdHolder, Annotation annotation, TypeConverter typeConverter) {
Class<? extends Annotation> type = annotation.annotationType();
RootBeanDefinition bd = (RootBeanDefinition) bdHolder.getBeanDefinition();
AutowireCandidateQualifier qualifier = bd.getQualifier(type.getName());//检查bean定义有没有这个type全限定类名的AutowireCandidateQualifier对象
if (qualifier == null) {
qualifier = bd.getQualifier(ClassUtils.getShortName(type));//没有的话看下有没短的类名的
}
if (qualifier == null) {
// First, check annotation on qualified element, if any
Annotation targetAnnotation = getQualifiedElementAnnotation(bd, type);//检查bean定义里是否设置了type类型的限定类
// Then, check annotation on factory method, if applicable
if (targetAnnotation == null) {
targetAnnotation = getFactoryMethodAnnotation(bd, type);//从工厂方法找是否有限定注解,这里frieds1的工厂方法上有Girl注解,所以得到了
}
if (targetAnnotation == null) {//从bean装饰的定义中找注解
RootBeanDefinition dbd = getResolvedDecoratedDefinition(bd);
if (dbd != null) {
targetAnnotation = getFactoryMethodAnnotation(dbd, type);
}
}
if (targetAnnotation == null) {//为空的话就从bean定义的目标类上去找
// Look for matching annotation on the target class
if (getBeanFactory() != null) {
try {
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;//找到就返回
}
}
// 匹配的限定注解的属性
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
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;
}
checkQualifiers部分2
如果前面判断不是Qualifier
注解的,就进行注解上的注解获取,然后继续判断是不是Qualifier
注解的。
if (checkMeta) {//不是Qualifier直接的注解,就获取注解的注解,进行isQualifier判断
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 && StringUtils.isEmpty(AnnotationUtils.getValue(metaAnn))) ||
!checkQualifier(bdHolder, metaAnn, typeConverter)) {
return false;//有Qualifier注解,不符合条件的就返回false
}
}
}
if (fallbackToMeta && !foundMeta) {//如果不是Qualifier直接,又没发现注解上有Qualifier注解就返回false
return false;
}
}
大致流程就是这样,主要是看bean
定义中是否有AutowireCandidateQualifier
对象,没有的话看是否设置了AnnotatedElement
对象,从这个上面去找有没有限定注解,再找不到从bean
定义的工厂方法上找注解,再不行就从bean定义的目标类上去找。有的话是否全限定名或者短类名和限定注解相同,相同的话获取属性值和限定注解的属性值匹配,匹配上表示就返回true
。
好了,今天就到这里了,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵。
Java 面试宝典是大明哥全力打造的 Java 精品面试题,它是一份靠谱、强大、详细、经典的 Java 后端面试宝典。它不仅仅只是一道道面试题,而是一套完整的 Java 知识体系,一套你 Java 知识点的扫盲贴。
它的内容包括:
- 大厂真题:Java 面试宝典里面的题目都是最近几年的高频的大厂面试真题。
- 原创内容:Java 面试宝典内容全部都是大明哥原创,内容全面且通俗易懂,回答部分可以直接作为面试回答内容。
- 持续更新:一次购买,永久有效。大明哥会持续更新 3+ 年,累计更新 1000+,宝典会不断迭代更新,保证最新、最全面。
- 覆盖全面:本宝典累计更新 1000+,从 Java 入门到 Java 架构的高频面试题,实现 360° 全覆盖。
- 不止面试:内容包含面试题解析、内容详解、知识扩展,它不仅仅只是一份面试题,更是一套完整的 Java 知识体系。
- 宝典详情:https://www.yuque.com/chenssy/sike-java/xvlo920axlp7sf4k
- 宝典总览:https://www.yuque.com/chenssy/sike-java/yogsehzntzgp4ly1
- 宝典进展:https://www.yuque.com/chenssy/sike-java/en9ned7loo47z5aw
目前 Java 面试宝典累计更新 400+ 道,总字数 42w+。大明哥还在持续更新中,下图是大明哥在 2024-12 月份的更新情况:
想了解详情的小伙伴,扫描下面二维码加大明哥微信【daming091】咨询
同时,大明哥也整理一套目前市面最常见的热点面试题。微信搜[大明哥聊 Java]或扫描下方二维码关注大明哥的原创公众号[大明哥聊 Java] ,回复【面试题】 即可免费领取。