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

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杂谈 作者zhang KaiTao

    1. spring杂谈[原创] 1.1 Spring事务处理时自我调用的解决方案及一些实现方式的风险 1.2 我对AOP的理解 1.3 Spring开闭原则的表现-BeanPostProcessor的扩展点-1 1.4 我对IoC/DI的理解 ...1.33 Spring 注入集合类型

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

    NULL 博文链接:https://fangguanhong.iteye.com/blog/1909830

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

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

    spring2.5学习PPT 传智博客

    09_Spring如何装配各种集合类型的属性 10_使用构造器装配属性 11_用@Resource注解完成属性装配 12_编码剖析@Resource注解的实现原理 13.@Autowire注解与自动装配 14.让Spring自动扫描和管理Bean 15.使用JDK中...

    通过@Autowired注解注入bean的顺序,以及@bean注入.rar

    通过@Bean 和spring的factoryBean注入的bean. 以及对应@service注解注入的类 通过@Autowired 注入对象的时间是现根据类型在根据beanName获取的案例集合

    Spring面试题含答案.pdf

    30. 在 Spring 中如何注入一个 java 集合? 31. 什么是 bean 装配? 32. 什么是 bean 的自动装配? 33. 解释不同方式的自动装配 34.自动装配有哪些局限性? 35. 你可以在 Spring 中注入一个 null 和一个空字符串吗?...

    spring.net中文手册在线版

    12.3.Spring.NET的通知类型 12.3.1.通知的生命周期 12.3.2.通知类型 12.3.2.1.拦截环绕通知 12.3.2.2.前置通知 12.3.2.3.异常通知 12.3.2.4.后置通知 12.3.2.5.引入通知 12.4.Spring.NET中的Advisor 12.5.使用...

    Spring的学习笔记

    七、 集合注入 12 八、 自动装配autowire 13 (一) byName 13 (二) byType 14 (三) 注意 14 九、 生命周期 15 (一) lazy-init/default-lazy-init 15 (二) init-method destroy-method 不要和prototype一起用(了解) ...

    Spring配置文件参数设置范例

    演示了Spring框架下 ...集合类型注入参数方式 自定义对象参数参数注入 以及简化模式注入 为避免使用者本地环境差异,此处验证类没有使用Junit插件,使用了Test,TestnamespaceC,TestnamespaceP三个类可分别单独运行

    Spring-Reference_zh_CN(Spring中文参考手册)

    6.8.1. 在Spring中使用AspectJ来为domain object进行依赖注入 6.8.1.1. @Configurable object的单元测试 6.8.1.2. 多application context情况下的处理 6.8.2. Spring中其他的AspectJ切面 6.8.3. 使用Spring IoC来...

    Spring攻略(第二版 中文高清版).part1

    1.6 为集合元素指定数据类型 24 1.6.1 问题 24 1.6.2 解决方案 24 1.6.3 工作原理 24 1.7 使用Spring的FactoryBean创建Bean 27 1.7.1 问题 27 1.7.2 解决方案 27 1.7.3 工作原理 27 1.8 使用工厂...

    Spring框架设值注入操作实战案例分析

    主要介绍了Spring框架设值注入操作,结合具体实例形式分析了spring框架设值注入相关实现与使用方法,需要的朋友可以参考下

    Spring.3.x企业应用开发实战(完整版).part2

    4.4.6 集合类型属性 4.4.7 简化配置方式 4.4.8 自动装配 4.5 方法注入 4.5.1 lookup方法注入 4.5.2 方法替换 4.6 之间的关系 4.6.1 继承 4.6.2 依赖 4.6.3 引用 4.7 整合多个配置文件 4.8 Bean作用域 4.8.1 ...

    springmybatis

    查询出列表,也就是返回list, 在我们这个例子中也就是 List&lt;User&gt; , 这种方式返回数据,需要在User.xml 里面配置返回的类型 resultMap, 注意不是 resultType, 而这个resultMap 所对应的应该是我们自己配置的 ...

    Spring攻略(第二版 中文高清版).part2

    1.6 为集合元素指定数据类型 24 1.6.1 问题 24 1.6.2 解决方案 24 1.6.3 工作原理 24 1.7 使用Spring的FactoryBean创建Bean 27 1.7.1 问题 27 1.7.2 解决方案 27 1.7.3 工作原理 27 1.8 使用工厂...

    spring2.5 学习笔记

    七、 集合注入 12 八、 自动装配autowire 13 (一) byName 13 (二) byType 14 (三) 注意 14 九、 生命周期 15 (一) lazy-init/default-lazy-init 15 (二) init-method destroy-method 不要和prototype一起用(了解) ...

    Spring in Action(第2版)中文版

    12.1.3在spring2中注入jndi对象 12.2发送电子邮件 12.2.1配置邮件发送器 12.2.2构建电子邮件 12.3调度任务 12.3.1使用javatimer调度任务 12.3.2使用quartz调度器 12.3.3按调度计划调用方法 12.4使用jmx管理...

    Spring in Action(第二版 中文高清版).part2

    3.3 注入非Spring Bean 3.4 注册自定义属性编辑器 3.5 使用Spring的特殊Bean 3.5.1 后处理Bean 3.5.2 Bean工厂的后处理 3.5.3 配置属性的外在化 3.5.4 提取文本消息 3.5.5 程序事件的解耦 3.5.6 让Bean了解...

Global site tag (gtag.js) - Google Analytics