Spring 注入集合类型
定义了一个类:
- @Service
- public class StringTest implements CachedRowSet,SortedSet<String>,Cloneable
- @Controller
- public class HomeController {
- @Autowired
- CachedRowSet message;
- @Autowired
- CachedRowSet message1;
- }
这里CachedRowSet , 等其他接口都是可以注入的,包括StringTest 也行。
但是使用:
- @Autowired
- SortedSet<String> message
就不行了。启动报错。
源码分析:
org.springframework.beans.factory.support.DefaultListableBeanFactory
- protected Object doResolveDependency(DependencyDescriptor descriptor, Class<?> type, String beanName,
- Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
- Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
- if (value != null) {
- if (value instanceof String) {
- String strVal = resolveEmbeddedValue((String) value);
- BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);
- value = evaluateBeanDefinitionString(strVal, bd);
- }
- TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
- return (descriptor.getField() != null ?
- converter.convertIfNecessary(value, type, descriptor.getField()) :
- converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
- }
- if (type.isArray()) {
- Class<?> componentType = type.getComponentType();
- Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType, descriptor);
- if (matchingBeans.isEmpty()) {
- if (descriptor.isRequired()) {
- raiseNoSuchBeanDefinitionException(componentType, "array of " + componentType.getName(), descriptor);
- }
- return null;
- }
- if (autowiredBeanNames != null) {
- autowiredBeanNames.addAll(matchingBeans.keySet());
- }
- TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
- return converter.convertIfNecessary(matchingBeans.values(), type);
- }
- else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
- Class<?> elementType = descriptor.getCollectionType();
- if (elementType == null) {
- if (descriptor.isRequired()) {
- throw new FatalBeanException("No element type declared for collection [" + type.getName() + "]");
- }
- return null;
- }
- Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType, descriptor);
- if (matchingBeans.isEmpty()) {
- if (descriptor.isRequired()) {
- raiseNoSuchBeanDefinitionException(elementType, "collection of " + elementType.getName(), descriptor);
- }
- return null;
- }
- if (autowiredBeanNames != null) {
- autowiredBeanNames.addAll(matchingBeans.keySet());
- }
- TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
- return converter.convertIfNecessary(matchingBeans.values(), type);
- }
- else if (Map.class.isAssignableFrom(type) && type.isInterface()) {
- Class<?> keyType = descriptor.getMapKeyType();
- if (keyType == null || !String.class.isAssignableFrom(keyType)) {
- if (descriptor.isRequired()) {
- throw new FatalBeanException("Key type [" + keyType + "] of map [" + type.getName() +
- "] must be assignable to [java.lang.String]");
- }
- return null;
- }
- Class<?> valueType = descriptor.getMapValueType();
- if (valueType == null) {
- if (descriptor.isRequired()) {
- throw new FatalBeanException("No value type declared for map [" + type.getName() + "]");
- }
- return null;
- }
- Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType, descriptor);
- if (matchingBeans.isEmpty()) {
- if (descriptor.isRequired()) {
- raiseNoSuchBeanDefinitionException(valueType, "map with value type " + valueType.getName(), descriptor);
- }
- return null;
- }
- if (autowiredBeanNames != null) {
- autowiredBeanNames.addAll(matchingBeans.keySet());
- }
- return matchingBeans;
- }
- else {
- Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
- if (matchingBeans.isEmpty()) {
- if (descriptor.isRequired()) {
- raiseNoSuchBeanDefinitionException(type, "", descriptor);
- }
- return null;
- }
- if (matchingBeans.size() > 1) {
- String primaryBeanName = determinePrimaryCandidate(matchingBeans, descriptor);
- if (primaryBeanName == null) {
- throw new NoUniqueBeanDefinitionException(type, matchingBeans.keySet());
- }
- if (autowiredBeanNames != null) {
- autowiredBeanNames.add(primaryBeanName);
- }
- return matchingBeans.get(primaryBeanName);
- }
- // We have exactly one match.
- Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
- if (autowiredBeanNames != null) {
- autowiredBeanNames.add(entry.getKey());
- }
- return entry.getValue();
- }
- }
从上边的源码大家可以看出:
1、首先判断注入的类型,如果是数组、Collection、Map,则注入的是元素数据,即查找与元素类型相同的Bean的注入到集合,而不是找跟集合类型相同的
2、对于Map,key只能是String类型,而且默认是Bean的名字
结论:
1、对于数组、集合、Map,注入的元素类型,如SortedSet<String> 其实是找所有String类型的Bean注入到集合
2、Map,key只能是String类型,而且默认是Bean的名字