spring注入list集合
spring在帮我们管理bean的时候,会帮我们完成自动注入,其中有一个比较特殊的类型:list
这篇笔记主要记录spring注入list集合的原理
应用
public interface Rest {}@Component
public class RestServiceImpl01 implements Rest{}@Component
public class RestServiceImpl02 implements Rest{}@Component
public class OrderService {@Autowired//@Qualifierprivate List<Rest> restList;public void test() {System.out.println("打印注入的集合的值,restList:" + restList);}
}public class Test {public static void main(String[] args) {AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);OrderService orderService = ac.getBean(OrderService.class);orderService.test();}
}
以上代码执行之后,打印的结果是:
打印注入的集合的值,restList:[com.spring.list.RestServiceImpl01@60611244, com.spring.list.RestServiceImpl02@3745e5c6]
spring中,在使用@Autowired注解注入list集合的时候,并不会根据List类型去容器中查找,而是根据list集合的元素类型,从spring容器中找到所有的实现类,放在list集合中,然后注入到bean中
那如果我们想要指定只注入部分bean怎么办呢?
@Component
public class OrderService {@Autowired@Qualifierprivate List<Rest> restList;public void test() {System.out.println("打印注入的集合的值,restList:" + restList);}
}
只需要把这的@Qualifier注解放开,然后在需要注入的bean上,加上这个注解
@Component
@Qualifier
public class RestServiceImpl02 implements Rest{}
此时再运行代码:打印注入的集合的值,restList:[com.spring.list.RestServiceImpl02@d706f19]
所以这就是注入list集合bean的应用
原理
对于bean的注入,如果我们使用的是@Autowired注解,会被AutowiredAnnotationBeanPostProcessor处理
链路:
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessPropertiesorg.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#injectorg.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#resolveFieldValueorg.springframework.beans.factory.support.DefaultListableBeanFactory#resolveDependencyorg.springframework.beans.factory.support.DefaultListableBeanFactory#doResolveDependency
在doResolveDependency方法中,有一个代码逻辑
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {return multipleBeans;
}
这里就是来解析list类型的
org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveMultipleBeans
else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {Class<?> elementType = descriptor.getResolvableType().asCollection().resolveGeneric();if (elementType == null) {return null;}// 在这里会取解析list集合中指定的接口所有的实现类Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType,new MultiElementDescriptor(descriptor));if (matchingBeans.isEmpty()) {return null;}if (autowiredBeanNames != null) {autowiredBeanNames.addAll(matchingBeans.keySet());}TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());Object result = converter.convertIfNecessary(matchingBeans.values(), type);if (getDependencyComparator() != null && result instanceof List) {((List<?>) result).sort(adaptDependencyComparator(matchingBeans));}return result;
}
在这个方法中,这段代码是来解析list集合的,所以只截取了这一部分代码,这一部分关键的代码是:findAutowireCandidates方法
protected Map<String, Object> findAutowireCandidates(@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {/*** 根据类型,获取当前beanDefinitionMap中的beanName,注意:这里是从beanDefinitionMap中获取的,并不是直接从spring* 容器中获取* 获取到的是待注入bean的name*/String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this, requiredType, true, descriptor.isEager());Map<String, Object> result = new LinkedHashMap<>(candidateNames.length);/*** resolvableDependencies:这里来遍历这个集合,判断要注入的bean是否是该类型的* resolvableDependencies这个集合,默认有四个值* interface org.springframework.context.ApplicationContext" -> {AnnotationConfigApplicationContext@1641}* interface org.springframework.beans.factory.BeanFactory" -> {DefaultListableBeanFactory@1630}* interface org.springframework.core.io.ResourceLoader" -> {AnnotationConfigApplicationContext@1641} * interface org.springframework.context.ApplicationEventPublisher -> {AnnotationConfigApplicationContext@1641}*/for (Class<?> autowiringType : this.resolvableDependencies.keySet()) {if (autowiringType.isAssignableFrom(requiredType)) {Object autowiringValue = this.resolvableDependencies.get(autowiringType);autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);if (requiredType.isInstance(autowiringValue)) {result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);break;}}}/*** 确切的说,是在isAutowireCandidate里面对Qualifier注解进行了判断* org.springframework.beans.factory.annotation.QualifierAnnotationAutowireCandidateResolver#isAutowireCandidate(org.springframework.beans.factory.config.BeanDefinitionHolder, org.springframework.beans.factory.config.DependencyDescriptor)*/for (String candidate : candidateNames) {if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {addCandidateEntry(result, candidate, descriptor, requiredType);}}if (result.isEmpty() && !indicatesMultipleBeans(requiredType)) {// Consider fallback matches if the first pass failed to find anything...DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();for (String candidate : candidateNames) {if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor)) {addCandidateEntry(result, candidate, descriptor, requiredType);}}if (result.isEmpty()) {// Consider self references as a final pass...// but in the case of a dependency collection, not the very same bean itself.for (String candidate : candidateNames) {if (isSelfReference(beanName, candidate) &&(!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&isAutowireCandidate(candidate, fallbackDescriptor)) {addCandidateEntry(result, candidate, descriptor, requiredType);}}}}return result;
}
在源码中,就是在isAutowireCandidate()这个方法中,对@Qualifier注解进行的过滤,也就是说,如果我们在注入list集合的时候,没有添加@Qualifier注解,那这个方法都会返回true,然后将所有的实现类都返回
如果加了@Qualifier注解,这里只有加了@Qualifier注解的实现类会返回TRUE,会被返回
这个方法的实现细节,待研究,debug看源码的时候,看到这样的结果
结论
所以,在spring中,我们在注入list集合的时候,如果只加了@Autowired注解,那就会把集合元素的所有实现类都注入进来,如果想只注入指定的类,那就使用@Qualifier注解
spring注入list集合相关推荐
- spring注入Map集合
[例]spring注入Map集合 创建User类 package com.shw; public class User {private String username;private String ...
- Spring高级应用之注入各类集合
先定义一个测试类,由于本文将要介绍注入各种集合时如何配置,故这个类包含各种集合,类名和属性名不好取,没有特殊含义: 1 2 3 4 5 6 7 8 9 publicclass Test { p ...
- Spring 注入集合的成员变量属性
Spring支持list,set,map和prop四种集合类型的注入. 看一个例子:JavaCollection这个类包含了上述介绍的4种集合类型的成员变量: import java.util.*; ...
- Spring 注入集合
转载自 Spring 注入集合 注入集合 你已经看到了如何使用 value 属性来配置基本数据类型和在你的 bean 配置文件中使用<property>标签的 ref 属性来配置对象引 ...
- Spring框架中集合属性为对象的注入方法
Spring框架中集合属性为对象的注入方法 前言 创建基础类 创建`Course`类 编写XML配置文件 创建测试类 执行结果 前言 在集合的属性注入中,如果注入属性为普通类型(String.int) ...
- ❤️Spring注入集合❤️(建议收藏)
❤️Spring注入集合 .以下是一些Spring常用的注入集合,请"食用",记得给个三连噢! 如果需要传递类似于 Java Collection 类型的值,例如 List.Set ...
- Spring框架教程集合
Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One J2EE Development a ...
- 跟杨春娟学Spring笔记:集合装配
跟杨春娟学Spring笔记:集合装配 完成:第一遍 1.常见集合元素有哪些? 集合元素 : 用途:装配list类型的值,允许重复 集合元素 : 用途:装配set类型的值,不允许重复 集合元素 : 用途 ...
- Spring注入(Injection)——教你一点一点知道什么是依赖注入及注入方式
前言 在学习spring的时候有个很重的知识点,那就是注入,不同的注入方式为程序的运行效率,资源利用都有不同的好处,接下来就看看我通过看视频总结的注入. 一.引入注入 1.首先我们明确一个问题,什么注 ...
最新文章
- flowable 配置自定义表单_Flowable用代码自定义流程
- DataGrid/DataList封装操作函数库!
- 二分+并查集【bzoj3007】[SDOI2012]拯救小云公主
- vscode 设置断点知乎_vscode 代码自动换行设置
- 如何利用火狐获取网址中的提交链接
- 关于如何清除某个特定网站的缓存---基于Chrome浏览器
- 与java线程有关的,线程多少和什么有关?大神们表示有话要说!
- 展讯召开2017全球合作伙伴大会,发布两款新平台及新战略
- 写给准备学习Linux的人
- 数据分析项目:母婴商品销量分析
- MongoDB 4.0 RC 版本强势登陆
- NBA球星为啥那么多顶薪?数据可视化为你揭晓真相
- js获取注册表中应用程序的路径,并通过注册表打开
- NoSQL Scylla Open Source 3.0食量比Cassandra大
- Mac电脑怎么远程桌面连接?
- 基于单片机万用表量程手动自动电阻电流电压设计-全套资料
- python基础学习-反射
- 老年人也能解决智能技术困难问题
- 华为用linux系统装eclipse,centos装eclipse
- 涂鸦Zigbee SDK开发系列教程——4.烧录授权
热门文章
- 《把时间当做朋友》书摘
- thinkpad t450 无线网卡m2 ngff接口改装苹果网卡 黑苹果系统macOS
- 责任链模式(doFilter)的123、321原理
- 高地环境APP技术支持-Email:zcj331@163.com
- 解密:404背后的故事
- Linux必会100个命令(四十三)useradd和userdel
- PHP 中流行的 rpc 框架有哪些
- Python 常见文件格式 .py .pyc .pyw .pyo .pyd 之间的主要区别
- k8s istio 虚拟机重启后出现upstream connect error or disconnect
- 业余时间可以做什么兼职副业?盘点几个业余兼职副业方式