`
jinnianshilongnian
  • 浏览: 21503299 次
  • 性别: Icon_minigender_1
博客专栏
5c8dac6a-21dc-3466-8abb-057664ab39c7
跟我学spring3
浏览量:2418510
D659df3e-4ad7-3b12-8b9a-1e94abd75ac3
Spring杂谈
浏览量:3008677
43989fe4-8b6b-3109-aaec-379d27dd4090
跟开涛学SpringMVC...
浏览量:5639384
1df97887-a9e1-3328-b6da-091f51f886a1
Servlet3.1规范翻...
浏览量:259904
4f347843-a078-36c1-977f-797c7fc123fc
springmvc杂谈
浏览量:1597271
22722232-95c1-34f2-b8e1-d059493d3d98
hibernate杂谈
浏览量:250212
45b32b6f-7468-3077-be40-00a5853c9a48
跟我学Shiro
浏览量:5858849
Group-logo
跟我学Nginx+Lua开...
浏览量:701954
5041f67a-12b2-30ba-814d-b55f466529d5
亿级流量网站架构核心技术
浏览量:785160
社区版块
存档分类
最新评论

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的名字

 

 

 

 

 

6
1
分享到:
评论
5 楼 15000346240 2015-10-12  
我有个类似的问题,对于这块不理解,所以也不知道怎么改了,求指点
我配置文件里是下面这样:
<bean id="clientTokenList" class="java.util.ArrayList">
    <constructor-arg>
      <list>
        <value>ZFc9dbkT</value>
        <value>qfafuFNy</value>
        <value>aGEAujhk</value>
        <value>dqYmYq5L</value>
        <value>jrED9vJ9</value>
.........
我controller里是下面这样
@Autowired
    @Qualifier("clientTokenList")
    private List<String> clientTokenList ;

这时候我要怎么写呢,因为这样就报你上面说的错误
4 楼 15000346240 2015-10-12  
jinnianshilongnian 写道
greemranqq 写道
感谢指点!
我还有点疑问:
  Class<?> elementType = descriptor.getCollectionType();   

这里代码是获得元素类型。是指什么呢。
比如我现在 创建一个Test2 的类。

然后 SortedSet<String>  和 SortedSet<Test1>

无论是注入集合SortedSet,还是 String  还是Test1 都出错,这里代码我还是没理清楚- -!

代码:
@Service
public class StringTest implements SortedSet<String>{
}

@Service
public class StringTest implements SortedSet<Test1>{
}


@Controller
public class HomeController {
@Autowired
String message;

@Autowired
Test1 message1;

}


错误信息:
严重: Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'homeController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: java.lang.String com.home.HomeController.message; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [java.lang.String] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:288)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1122)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:522)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)



无论是注入集合SortedSet,还是 String  还是Test1 都出错,这里代码我还是没理清楚- -!
如Set<String> ms  即查找所有类型为String的注入到这个集合


No qualifying bean of type [java.lang.String] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency.
@Autowired
String message;  没有找到类型为String的bean


那这种情况怎么写呢?愚钝。
3 楼 飞天奔月 2013-05-12  
以前我也遇到这样的问题

也是看源码才知道问题所在
2 楼 jinnianshilongnian 2013-05-06  
greemranqq 写道
感谢指点!
我还有点疑问:
  Class<?> elementType = descriptor.getCollectionType();   

这里代码是获得元素类型。是指什么呢。
比如我现在 创建一个Test2 的类。

然后 SortedSet<String>  和 SortedSet<Test1>

无论是注入集合SortedSet,还是 String  还是Test1 都出错,这里代码我还是没理清楚- -!

代码:
@Service
public class StringTest implements SortedSet<String>{
}

@Service
public class StringTest implements SortedSet<Test1>{
}


@Controller
public class HomeController {
@Autowired
String message;

@Autowired
Test1 message1;

}


错误信息:
严重: Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'homeController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: java.lang.String com.home.HomeController.message; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [java.lang.String] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:288)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1122)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:522)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)



无论是注入集合SortedSet,还是 String  还是Test1 都出错,这里代码我还是没理清楚- -!
如Set<String> ms  即查找所有类型为String的注入到这个集合


No qualifying bean of type [java.lang.String] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency.
@Autowired
String message;  没有找到类型为String的bean
1 楼 greemranqq 2013-05-06  
感谢指点!
我还有点疑问:
  Class<?> elementType = descriptor.getCollectionType();   

这里代码是获得元素类型。是指什么呢。
比如我现在 创建一个Test2 的类。

然后 SortedSet<String>  和 SortedSet<Test1>

无论是注入集合SortedSet,还是 String  还是Test1 都出错,这里代码我还是没理清楚- -!

代码:
@Service
public class StringTest implements SortedSet<String>{
}

@Service
public class StringTest implements SortedSet<Test1>{
}


@Controller
public class HomeController {
@Autowired
String message;

@Autowired
Test1 message1;

}


错误信息:
严重: Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'homeController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: java.lang.String com.home.HomeController.message; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [java.lang.String] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:288)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1122)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:522)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)

相关推荐

    Wasabi1234#Java-Interview-Tutorial#Spring 注入集合类型1

    1.1 收集方式 1.2 直接装配方式 2.1 收集装配 2.2 直接装配方式

    Spring中集合类型的装配

    在Spring框架中,集合类型的装配是一项重要的功能,它允许我们把多个同类型的bean注入到一个集合对象中,如List、Set、Map等。这在处理依赖关系时非常有用,特别是当我们需要管理一组相似对象或者需要根据配置动态...

    Spring对集合的装配(各种集合类型的属性的注入方式)

    在Spring框架中,集合装配是将一组对象注入到如List、Set、Map等集合类型属性中的过程。这个过程是依赖注入(Dependency Injection,DI)的一个重要方面,它使得应用程序更加灵活,易于测试和维护。本篇文章将深入...

    Spring_Spring_教程8_注入_复杂类型的注入

    Spring支持对List、Set、Map等集合类型的注入。例如,你可以声明一个Bean,其属性是一个List,并在配置文件或使用Java配置类时提供具体的元素值。这使得在运行时,Spring会自动创建对应的集合并填充数据。 2. ...

    第四章 Spring4 注入参数

    Spring4对注入参数的支持更加完善,本章将深入探讨Spring4中的参数注入机制,包括基本类型注入、对象注入、集合类型注入以及如何通过注解实现这些功能。 一、基本类型注入 Spring4允许我们将基本数据类型(如int、...

    spring-集合注入、自定义转换器

    集合注入允许我们在Spring配置中将一组对象注入到单个bean属性中,这些对象通常以集合类型(如List、Set、Map等)存在。这样做的好处是可以方便地管理多个依赖项,而无需为每个依赖项创建单独的bean。 例如,假设...

    Spring - -setter方式 向bean中注入各种类型的值

    4. **集合类型的注入**:对于List、Set、Map等集合类型,Spring可以批量注入多个值。在XML配置中,你可以使用`&lt;list&gt;`、`&lt;set&gt;`或`&lt;map&gt;`标签来定义这些集合,并提供多个子元素。在Java配置中,可以使用`@Autowired`...

    spring集合属性

    在Spring框架中,集合属性(Collections Property)是一个重要的概念,它允许我们配置bean的属性为集合类型,如List、Set、Map等。这些集合可以由Spring容器动态填充,提供了极大的灵活性和可配置性,使得我们可以...

    spring 设值注入

    设值注入不仅限于字符串,还可以注入其他类型的值,如基本类型、集合、其他bean引用等。例如,你可以注入一个列表: ```xml &lt;value&gt;1 &lt;value&gt;2 &lt;value&gt;3 ``` 或者,使用SpEL(Spring Expression ...

    spring 普通属性注入

    2. **XML中的Map集合注入** 当我们需要注入一个Map时,Spring提供了特殊的`&lt;map&gt;`标签。不同于其他标签,`&lt;entry&gt;`子标签用于定义键值对: ```xml ``` 在这个例子中,`myBean`的`myMap`属性...

    第五章 Spring4 自动装配、方法注入

    此外,Spring4还支持对集合类型的自动装配,如List、Set、Map等。 为了更好地实践这些概念,我们可以查看压缩包中的Spring0501文件,这可能包含了示例代码或教程资源。通过实际操作和调试,你可以更深入地理解和...

    Springioc注入Demo

    5. **属性注入**:除了基本类型的属性外,Spring还能处理复杂类型的属性注入,如集合(List、Set、Map等)、自定义对象等。对于集合,可以通过`@Resource`或`@Autowired`注解配合`@Value`来注入值,对于自定义对象,...

    Spring配置文件集合

    7. `spring-aop.xml`: 用于配置Spring的AOP(面向切面编程)相关设置,如定义切面、通知类型等,使得我们可以进行横切关注点的处理,如日志记录、事务管理等。 8. `log4j.xml`: 该文件是Log4j的日志配置,定义了...

    装配bean—集合类型注入值源码

    装配bean——集合类型注入值: 本文介绍数组、list集合、set集合、map集合、properties的注值 博客原文地址:http://blog.csdn.net/tingzhiyi/article/details/52104203

    day38 14-Spring的Bean的属性的注入:集合属性的注入

    在本主题“day38 14-Spring的Bean的属性的注入:集合属性的注入”中,我们将深入探讨如何向Bean注入集合类型的属性,如List、Set、Map等。这在实际开发中非常常见,因为很多情况下我们需要处理一组相关的数据。 ...

    java Spring DI依赖注入.rar

    Spring的依赖注入不仅限于bean之间的关系,还可以用于注入集合类型,如List、Set、Map等,甚至可以处理复杂类型的依赖注入,如接口类型的多实现。 在`chapter8`这个文件夹中,可能包含了关于Spring依赖注入的深入...

    spring各种属性的注入

    本文档主要介绍了在Spring配置文件中如何进行各种类型的属性注入,包括基本类型、集合类型以及Bean之间的引用等。下面将逐一展开介绍每种注入方式的细节及其应用场景。 #### 基本类型属性注入 基本类型的属性注入...

    Spring (bean怎样注入值)学习实例

    本文将深入探讨如何在Spring中通过XML配置文件对Bean进行值的注入,包括List、Set和Map等集合类型的注入。 首先,我们需要了解Spring Bean的定义。在Spring中,Bean是一个被Spring容器管理的对象,它可以通过XML、...

    Spring学习笔记(7)----装配各种集合类型的属性

    在Spring框架的学习中,"装配各种集合类型的属性"是一个重要的概念,这涉及到如何将不同的集合对象,如List、Set、Map等,与Spring的依赖注入(Dependency Injection, DI)机制相结合,实现灵活的配置和管理。...

Global site tag (gtag.js) - Google Analytics