Spring按类型自动装配注入数组、集合、Map

Spring按类型自动装配注入数组、集合、Map时,是把应用上下文中对应类型的bean装配进集合,而不是直接查找一个对应类型的集合然后注入。以下面这段代码为例:

@Component
public class WmsProtocolFactory {

    @Autowired
    private Map<String, WmsRemoteProtocol> mediaPlayerMap;

    @Autowired
    private WmsRemoteProtocol[] addr;
    @Autowired
    private List<WmsRemoteProtocol> list;

    HashMap<Object,WmsRemoteProtocol> map = Maps.newHashMap();
    public WmsProtocolFactory(List<WmsRemoteProtocol> wmsRemoteProtocolList){
        for(WmsRemoteProtocol wmsRemoteProtocol :wmsRemoteProtocolList){
            map.put(wmsRemoteProtocol.getType(),wmsRemoteProtocol);
        }
    }

    public void printInfo(){
       System.out.println("map----->"+mediaPlayerMap);
   	   System.out.println("数组----->"+addr);
       System.out.println("集合----->"+list);
       System.out.println("定制map----->"+map);
    }
    /**
     * 功能描述:
     * 获取远程调用的具体实现
     *
     * @param:
     * @return:
     * @auther: baojl514
     */
    public WmsRemoteProtocol getProtocol(String chnlCode){
        return map.get(chnlCode);
  }
}

下面是打印出来的各种类型

map----->{infoWmsComp=com.csj.tiger.service.wms.InfoWmsComp@2ba7828b, sharkWmsComp=com.csj.tiger.service.wms.SharkWmsComp@1e686da2, defaultVirtualClient=com.csj.tiger.chnl.routing.DefaultVirtualProtocol@51653509, jmarsWmsComp=com.csj.tiger.jmars.component.impl.JmarsWmsComp@7abe3d53, misComp=com.csj.tiger.mis.component.impl.MisComp@43347199}
数组----->[Lcom.csj.tiger.chnl.routing.WmsRemoteProtocol;@1e5bac73
集合----->[com.csj.tiger.service.wms.InfoWmsComp@2ba7828b, com.csj.tiger.service.wms.SharkWmsComp@1e686da2, com.csj.tiger.chnl.routing.DefaultVirtualProtocol@51653509, com.csj.tiger.jmars.component.impl.JmarsWmsComp@7abe3d53, com.csj.tiger.mis.component.impl.MisComp@43347199]
定制map----->{0=com.csj.tiger.chnl.routing.DefaultVirtualProtocol@51653509, SHARK=com.csj.tiger.service.wms.SharkWmsComp@1e686da2, JMARS=com.csj.tiger.jmars.component.impl.JmarsWmsComp@7abe3d53, INFO=com.csj.tiger.service.wms.InfoWmsComp@2ba7828b, JMIS=com.csj.tiger.mis.component.impl.MisComp@43347199}

最后一个定制map是根据不同的bean中type类型返回对应的bean,用于路由的设计。

Spring会查找应用上下文里可赋给MediaPlayer类型的bean放进mediaPlayerArr数组,查找可赋给MediaPlayer类型的bean放进mediaPlayerList,查找可赋给MediaPlayer类型的bean put进mediaPlayerMap,key为bean的name。

public Object doResolveDependency(DependencyDescriptor descriptor, String beanName, Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
        InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);

    try {
        Object shortcut = descriptor.resolveShortcut(this);
        if (shortcut != null) {
            Object var17 = shortcut;
            return var17;
        } else {
            Class<?> type = descriptor.getDependencyType();
            Object value = this.getAutowireCandidateResolver().getSuggestedValue(descriptor);
            Object var20;
            if (value == null) {
                Object multipleBeans = this.resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
                if (multipleBeans == null) {
                    Map<String, Object> matchingBeans = this.findAutowireCandidates(beanName, type, descriptor);
                    String autowiredBeanName;
                    if (matchingBeans.isEmpty()) {
                        if (this.isRequired(descriptor)) {
                            this.raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
                        }

                        autowiredBeanName = null;
                        return autowiredBeanName;
                    } else {
                        Object instanceCandidate;
                        Object var13;
                        if (matchingBeans.size() > 1) {
                            autowiredBeanName = this.determineAutowireCandidate(matchingBeans, descriptor);
                            if (autowiredBeanName == null) {
                                if (!this.isRequired(descriptor) && this.indicatesMultipleBeans(type)) {
                                    var13 = null;
                                    return var13;
                                }

                                var13 = descriptor.resolveNotUnique(type, matchingBeans);
                                return var13;
                            }

                            instanceCandidate = matchingBeans.get(autowiredBeanName);
                        } else {
                            Entry<String, Object> entry = (Entry)matchingBeans.entrySet().iterator().next();
                            autowiredBeanName = (String)entry.getKey();
                            instanceCandidate = entry.getValue();
                        }

                        if (autowiredBeanNames != null) {
                            autowiredBeanNames.add(autowiredBeanName);
                        }

                        var13 = instanceCandidate instanceof Class ? descriptor.resolveCandidate(autowiredBeanName, type, this) : instanceCandidate;
                        return var13;
                    }
                } else {
                    var20 = multipleBeans;
                    return var20;
                }
            } else {
                if (value instanceof String) {
                    String strVal = this.resolveEmbeddedValue((String)value);
                    BeanDefinition bd = beanName != null && this.containsBean(beanName) ? this.getMergedBeanDefinition(beanName) : null;
                    value = this.evaluateBeanDefinitionString(strVal, bd);
                }

                TypeConverter converter = typeConverter != null ? typeConverter : this.getTypeConverter();
                var20 = descriptor.getField() != null ? converter.convertIfNecessary(value, type, descriptor.getField()) : converter.convertIfNecessary(value, type, descriptor.getMethodParameter());
                return var20;
            }
        }
    } finally {
        ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
    }
}

private Object resolveMultipleBeans(DependencyDescriptor descriptor, String beanName, Set<String> autowiredBeanNames, TypeConverter typeConverter) {
    Class<?> type = descriptor.getDependencyType();
    Class valueType;
    Map matchingBeans;
    Class elementType;
    if (type.isArray()) {
        elementType = type.getComponentType();
        ResolvableType resolvableType = descriptor.getResolvableType();
        valueType = resolvableType.resolve();
        if (valueType != null && valueType != type) {
            type = valueType;
            elementType = resolvableType.getComponentType().resolve();
        }

        if (elementType == null) {
            return null;
        } else {
            matchingBeans = this.findAutowireCandidates(beanName, elementType, new DefaultListableBeanFactory.MultiElementDescriptor(descriptor));
            if (matchingBeans.isEmpty()) {
                return null;
            } else {
                if (autowiredBeanNames != null) {
                    autowiredBeanNames.addAll(matchingBeans.keySet());
                }

                TypeConverter converter = typeConverter != null ? typeConverter : this.getTypeConverter();
                Object result = converter.convertIfNecessary(matchingBeans.values(), type);
                if (this.getDependencyComparator() != null && result instanceof Object[]) {
                    Arrays.sort((Object[])((Object[])result), this.adaptDependencyComparator(matchingBeans));
                }

                return result;
            }
        }
    } else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
        elementType = descriptor.getResolvableType().asCollection().resolveGeneric(new int[0]);
        if (elementType == null) {
            return null;
        } else {
            Map<String, Object> matchingBeans = this.findAutowireCandidates(beanName, elementType, new DefaultListableBeanFactory.MultiElementDescriptor(descriptor));
            if (matchingBeans.isEmpty()) {
                return null;
            } else {
                if (autowiredBeanNames != null) {
                    autowiredBeanNames.addAll(matchingBeans.keySet());
                }

                TypeConverter converter = typeConverter != null ? typeConverter : this.getTypeConverter();
                Object result = converter.convertIfNecessary(matchingBeans.values(), type);
                if (this.getDependencyComparator() != null && result instanceof List) {
                    Collections.sort((List)result, this.adaptDependencyComparator(matchingBeans));
                }

                return result;
            }
        }
    } else if (Map.class == type) {
        ResolvableType mapType = descriptor.getResolvableType().asMap();
        Class<?> keyType = mapType.resolveGeneric(new int[]{0});
        if (String.class != keyType) {
            return null;
        } else {
            valueType = mapType.resolveGeneric(new int[]{1});
            if (valueType == null) {
                return null;
            } else {
                matchingBeans = this.findAutowireCandidates(beanName, valueType, new DefaultListableBeanFactory.MultiElementDescriptor(descriptor));
                if (matchingBeans.isEmpty()) {
                    return null;
                } else {
                    if (autowiredBeanNames != null) {
                        autowiredBeanNames.addAll(matchingBeans.keySet());
                    }

                    return matchingBeans;
                }
            }
        }
    } else {
        return null;
    }
}

我们可以看到在resolveMultipleBeans方法中:

如果是数组,则获取数组元素类型,查找匹配该类型的所有bean,返回一个这些bean的数组;
如果该类可赋给Collection,并且是一个接口,则获取集合元素类型,查找匹配该类型的所有bean,返回一个这些bean的集合;
如果该类型是Map(注意是type == Map.class),且key是String类型,则获取Map的value的类型,查找匹配该类型的所有bean,这是一个key为bean name、value为bean实例的一个Map,返回这个Map。
其他情况则是我们所熟知的按类型自动装配过程。

引:https://blog.csdn.net/nlznlz/article/details/82528411

上一篇:4-5 接口的继承


下一篇:栈桢与操作数栈以及符号引用与直接引用的转换