Spring autowired 属性注入候选 Bean 数量大于一个时选择注入 Bean 的优先级

结论

  1. 标记有 @Qualifier 的 autowired 属性会在 DefaultListableBeanFactory#doResolveDependency -> resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter) -> … -> QualifierAnnotationAutowireCandidateResolver#checkQualifiers 过滤掉与 Qualifier.value() 不匹配的 bean
// @see org.springframework.beans.factory.support.DefaultListableBeanFactory#findAutowireCandidates

for (String candidate : candidateNames) {
    // isAutowireCandidate(candidate, descriptor) 内部实现可以根据 descriptor#getAnnotations 列表判断   	   
    // 需不需要排除不满足 Qualifier 的 bean
    if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
        addCandidateEntry(result, candidate, descriptor, requiredType);
    }
}

// ContextAnnotationAutowireCandidateResolver extends QualifierAnnotationAutowireCandidateResolver
// @see org.springframework.beans.factory.annotation.QualifierAnnotationAutowireCandidateResolver#checkQualifiers
  1. 优先匹配标记有 @Primary 的 Bean
  2. 优先匹配标记有 @javax.annotation.Priority 的 Bean
  3. 优先匹配与 autowired 字段或方法参数名称相同的 Bean
// @see org.springframework.beans.factory.config.DependencyDescriptor#getDependencyName

/**
 * Determine the name of the wrapped parameter/field.
 * @return the declared name (never {@code null})
 */
@Nullable
public String getDependencyName() {
    return (this.field != null ? this.field.getName() : obtainMethodParameter().getParameterName());
}
  1. 如果1、2、3无法确定确定唯一的匹配的 Bean 名称,返回 null
  2. 4 返回 null 时,autowired 对象属性 required = true 且 autowired 属性不是一个多值类型(如 Collection、数组、Map)、抛出 NoUniqueBeanDefinitionException 异常
// @see org.springframework.beans.factory.config.DependencyDescriptor#resolveNotUnique

@Nullable
public Object resolveNotUnique(ResolvableType type, Map<String, Object> matchingBeans) throws BeansException {
    throw new NoUniqueBeanDefinitionException(type, matchingBeans.keySet());
}

解析源码参见

org.springframework.beans.factory.support.DefaultListableBeanFactory#doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter)

Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
    if (isRequired(descriptor)) {
        raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
    }
    return null;
}

String autowiredBeanName;
Object instanceCandidate;
// 匹配 Bean 数量大于一个
if (matchingBeans.size() > 1) {
    autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
    if (autowiredBeanName == null) {
        if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
            return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
        }
        else {
            // In case of an optional Collection/Map, silently ignore a non-unique case:
            // possibly it was meant to be an empty collection of multiple regular beans
            // (before 4.3 in particular when we didn't even look for collection beans).
            return null;
        }
    }
    instanceCandidate = matchingBeans.get(autowiredBeanName);
}
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
		Class<?> requiredType = descriptor.getDependencyType();
    String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
    if (primaryCandidate != null) {
        return primaryCandidate;
    }
    String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
    if (priorityCandidate != null) {
        return priorityCandidate;
    }
    // Fallback
    for (Map.Entry<String, Object> entry : candidates.entrySet()) {
        String candidateName = entry.getKey();
        Object beanInstance = entry.getValue();
        if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
            matchesBeanName(candidateName, descriptor.getDependencyName())) {
            return candidateName;
        }
    }
    return null;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值