怎么根据 Bean的类型去找
我们进入 getBeanNamesForType方法, 具体如下图所示
doGetBeanNamesForType方法
这个方法太长了, 而且我看着真的蒙, 简单讲一下流程, 感兴趣的话大家自己看一下:
- 遍历 BeanDefinition
- 判断bean名字前有没有&符号, 有的话去处理掉
- 拿取 BeanDefinition的属性判断当前的是否匹配
返回
我们回到本方法的开头, 只要知道这个方法是从 BeanFactory中找出和 requiredType所匹配的 beanName, 仅仅是 beanName, 这些 bean不一定经过了实例化, 只有到最终确定某个 Bean了, 如果这个Bean还没有实例化才会进行实例化
resolvableDependencies
在 Spring启动的时候就会忘这个 map中存东西,
Bean对象加入到集合
然后去遍历这个 map, 获取到 key也就是 Bean类型, 判断有没有相同的 Bean类型, 如果有就把对应的对象加入到我们的返回数组中
遍历判断是不是自己注入自己
- 如果不是自己注入自己,则判断该candidate到底能不能用来进行自动注入
- 注入非自己
- 如果有多个candidate 最终将匹配成功 candidate加入到 result
- 因为有多个, 且result不为空
- 所以直接返回 result
result.isEmpty()
- 假设有多个 candidate, 且都不匹配, result == null
- 则会去判断需要的类型是不是 Map, 数组之类的
- 中间那个for循环用的很少 , 就先不看了
- 如果匹配的是自己, 就将自己添加到result中
返回
然后去判断 如果没有找到 Bean则抛出异常
如果找到了多个 Bean
如图所示, 如果根据 beanName找到了多个 Bean那么该 if判断则为 true
determineAutowireCandidate方法
- 遍历 map获取对应的 beanName和 ( bean对象或 Class类)
- isPrimary方法, 判断这多个 Bean有没有否实现了 @isPrimary注解
- 如果都实现了 @isPrimary注解则抛出异常
- 如果只有一个实现了 @isPrimary注解则使用这个 Bean
方法结束, 返回上一层 determineAutowireCandidate方法
determineHighestPriorityCandidate方法
方法流程如下:
- 遍历map
- 取当前某个Bean的优先级是什么
- 获取 @Priority注解, 方法在下图红框位置
@Priority 该注解不能使用在方法上, 只能使用在类上面
@Order在依赖注入中是没有去使用判断的
方法结束, 返回上一层 determineAutowireCandidate方法
通过源码可以看到 @Resource 和 @Autowired的区别 如果有多个同名beanName, 那么@Autowired 会先去寻找有没有哪个 bean是有 @Primary注解的, 如果都没有, 则去寻找有没有哪个类上是有 @Priority优先级注解的, 如果都没有则会去按照名称查找 这个面试题在刚毕业的时候也是经常被问到的, 以前只知道答案, 这次通过源码对其的解答也更加清晰明了了
返回
接下来返回到下面红框的位置, 继续玩下走
如果没有找到对象, required == true抛出异常, 如果不为 true则返回 null, 然后赋值
如果只找到了一个 Bean
那么直接为之前定义的 autowiredBeanName 和 instanceCandidate进行赋值
如果找到了Bean
如果找到了Bean , 则进行记录
判断 instanceCandidate是不是一个类
如果是一个类, 那么获取这个类的 bean
去判断这个类型是不是 NullBean
NullBean的定义代码如下所示, 当以下面的方式定义一个 bean的时候, 这个bean存在 map中的 key为 JuejinService, value为 NullBean
@Bean public JuejinService juejinService(){ return null; } 复制代码
相关判断代码如下所示
最后返回 over
最后红框判断的是期望类型和实际获取到的类型是否一致问题, 就不详细解释了