@Autowire注入集合类方式深入解析

​@Autowire依赖注入集合类注入方式

 

相信大家对@Autowire的使用并不陌生,这里就不对它做太多介绍,本章核心将对@Autowire如何处理集合类方式做深入探讨,首先创建两个user类实现user接口,

然后再写一个集合封装类

好了,最后写一个测试类

查看测试结果:

通过结果,我们可以看到@Autowire将我们实现User接口的所有类都进存放在集合中,存放的类型既有Map类型的方式,也有List的方式。

@Autowire注入集合类方式源码解析

在DefaultListableBeanFactory存在一个方法resolveMultipleBeans,这个方法就是解决依赖注入集合类方式的核心代码,我们先简略看一下,可以找到在代码中有几个重要的判断,    else if (type.isArray()),else if (Collection.class.isAssignableFrom(type) && type.isInterface()) , else if (Map.class == type),那么读者应该有些明白了,没错这里就是Spring处理集合类的核心代码,我们用IDEA调试一下,注意这里先采用Map接口的方式调试

@Nullable
  private Object resolveMultipleBeans(DependencyDescriptor descriptor, @Nullable String beanName,
      @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) {
​
    final Class<?> type = descriptor.getDependencyType();
​
    if (descriptor instanceof StreamDependencyDescriptor) {
      Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
      if (autowiredBeanNames != null) {
        autowiredBeanNames.addAll(matchingBeans.keySet());
      }
      Stream<Object> stream = matchingBeans.keySet().stream()
          .map(name -> descriptor.resolveCandidate(name, type, this))
          .filter(bean -> !(bean instanceof NullBean));
      if (((StreamDependencyDescriptor) descriptor).isOrdered()) {
        stream = stream.sorted(adaptOrderComparator(matchingBeans));
      }
      return stream;
    }
    else if (type.isArray()) {
      Class<?> componentType = type.getComponentType();
      ResolvableType resolvableType = descriptor.getResolvableType();
      Class<?> resolvedArrayType = resolvableType.resolve(type);
      if (resolvedArrayType != type) {
        componentType = resolvableType.getComponentType().resolve();
      }
      if (componentType == null) {
        return null;
      }
      Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType,
          new MultiElementDescriptor(descriptor));
      if (matchingBeans.isEmpty()) {
        return null;
      }
      if (autowiredBeanNames != null) {
        autowiredBeanNames.addAll(matchingBeans.keySet());
      }
      TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
      Object result = converter.convertIfNecessary(matchingBeans.values(), resolvedArrayType);
      if (result instanceof Object[]) {
        Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
        if (comparator != null) {
          Arrays.sort((Object[]) result, comparator);
        }
      }
      return result;
    }
    else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
      Class<?> elementType = descriptor.getResolvableType().asCollection().resolveGeneric();
      if (elementType == null) {
        return null;
      }
      Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType,
          new MultiElementDescriptor(descriptor));
      if (matchingBeans.isEmpty()) {
        return null;
      }
      if (autowiredBeanNames != null) {
        autowiredBeanNames.addAll(matchingBeans.keySet());
      }
      TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
      Object result = converter.convertIfNecessary(matchingBeans.values(), type);
      if (result instanceof List) {
        Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
        if (comparator != null) {
          ((List<?>) result).sort(comparator);
        }
      }
      return result;
    }
    else if (Map.class == type) {
      ResolvableType mapType = descriptor.getResolvableType().asMap();
      Class<?> keyType = mapType.resolveGeneric(0);
      if (String.class != keyType) {
        return null;
      }
      Class<?> valueType = mapType.resolveGeneric(1);
      if (valueType == null) {
        return null;
      }
      Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType,
          new MultiElementDescriptor(descriptor));
      if (matchingBeans.isEmpty()) {
        return null;
      }
      if (autowiredBeanNames != null) {
        autowiredBeanNames.addAll(matchingBeans.keySet());
      }
      return matchingBeans;
    }
    else {
      return null;
    }
  }

首先获取我们属性的类型,这里是对应users

可以看到这里进入了这个判断,那么这里就是真正处理集合类的代码了,我们逐一分析,

前面是获取我们需要解析的集合信息并且进行封装,然后进行校验,然后将代码停在findAutowireCandidates这个方法上,我们先执行

可以看到这里已经做好了我们需要的东西,也就是说这个方法做了我们集合处理的核心工作,我们进入这个方法进行深入了解。

protected Map<String, Object> findAutowireCandidates(
      @Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
​
    String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
        this, requiredType, true, descriptor.isEager());
    Map<String, Object> result = new LinkedHashMap<>(candidateNames.length);
    for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {
      Class<?> autowiringType = classObjectEntry.getKey();
      if (autowiringType.isAssignableFrom(requiredType)) {
        Object autowiringValue = classObjectEntry.getValue();
        autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
        if (requiredType.isInstance(autowiringValue)) {
          result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
          break;
        }
      }
    }
    for (String candidate : candidateNames) {
      if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
        addCandidateEntry(result, candidate, descriptor, requiredType);
      }
    }
    if (result.isEmpty()) {
      boolean multiple = indicatesMultipleBeans(requiredType);
      // Consider fallback matches if the first pass failed to find anything...
      DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
      for (String candidate : candidateNames) {
        if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor) &&
            (!multiple || getAutowireCandidateResolver().hasQualifier(descriptor))) {
          addCandidateEntry(result, candidate, descriptor, requiredType);
        }
      }
      if (result.isEmpty() && !multiple) {
        // Consider self references as a final pass...
        // but in the case of a dependency collection, not the very same bean itself.
        for (String candidate : candidateNames) {
          if (isSelfReference(beanName, candidate) &&
              (!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
              isAutowireCandidate(candidate, fallbackDescriptor)) {
            addCandidateEntry(result, candidate, descriptor, requiredType);
          }
        }
      }
    }
    return result;
  }
​

首先获取了我们实现User接口的所有类名称

然后进行循环

注意这里的循环值是我们Spring内建的游离对象,这里为什么会循环这些内建对象呢?其实很简单,在《BeanFactory和ApplicationContext的区别》的章节里,笔者提到了

这种方式的数据来源,这里就是解决这类问题的,因为我们都知道Spring内部忽略了这些类型,所以如果不再这里注入,如果我们需要注入这些属性就会失效。好了我们继续

这里又是一个循环,这个循环就比较简单了,无非就是向result开始赋值,赋值完成后就能够得到我们所需要的集合类型,那么它是如何赋值的呢?

我们简要看一下,这里又是descriptor.resolveCandidate,这个方法可能大家并不熟悉,我们点进去看看

现在大家熟悉了吧!那么这就不再多细说了吧。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值