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