Spring5.2.x-03-自动注入模型

知识点笔记

  1. spring是对构造方法做推断来实例化bean
  2. Spring有自己的推断模型, 改变推断模型会改变Spring对构造方法的选择

AbstractAutowireCapableBeanFactory抽象类中的createBeanInstance方法里的一行代码
// 推测需要的构造方法
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);

无参构造方法为 null, 会通过clazz.getDeclaredConstructor();最后走反射ctor.newInstance(argsWithDefaultValues);获取

但内部类不会, Spring会默认编入一个传入父类作为参数的构造方法

手动注入
通过xml明确指定如何注入 NO = 0
自动注入
AbstractBeanDefinition.AUTOWIRE_BY_NAME = 1
AbstractBeanDefinition.AUTOWIRE_BY_TYPE = 2
AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR = 3

@Autowired是自动注入还是手动注入?

依赖注入是一种过程, 文档上说是基于构造方法的注入和基于Setter方法的注入

根据类型和根据名字的区别

ByType和ByName的区别
比如有一个方法

public void setByType(N n) {
	log.debug("setter N:{}",n);
}

byNmae, 用的是beanName, 理论上就是n
byType, 用的是set后面的名字, byType

@AutoWired和@Resource的主要区别

@AutoWired
先根据类型, 再根据名字
不仅仅是先根据类型找, 先找到a和b, 再根据名字去筛选, 找到一个

@Resource
先根据名字, 再根据类型

@AutoWired的工作原理
AutowiredAnnotationBeanPostProcessor, 可以加到属性上, 可以加到方法上, 用两个内部类

629行左右的inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs)方法解析

解析
value = resolveFieldValue(field, bean, beanName);
->DefaultListableBeanFactory#resolveMultipleBeans

resolveMultipleBeans(): 如果是array/list/map等, 走这里来解析完成查找, 把所有的bean直接注入进来

获取类型(拿到class): Class<?> type = descriptor.getDependencyType();

findAutowireCandidates(): 先根据类型找到该类型所有类的bean名字String[] candidateNames, 如果找到多个就放到map里, 再根据名字(实例名字)来找, 找到一个就返回

@Resource的工作原理

CommonAnnotationBeanPostProcessor和AutowiredAnnotationBeanPostProcessor, 两者都有的方法postProcessProperties()方法, 一个找标记@Autowired的一个找@Resource的

AutowiredAnnotationBeanPostProcessor#postProcessProperties => 会扫描出有@Autowired的玩意(field或method), 放到InjectionMetadata的属性injectedElements集合里

遍历injectedElements集合, 调用每个对象(InjectedElement)的inject方法, @Autowired的InjectedElement重写了Field和Method方法(先类型再名字), @Resource的InjectedElement用的是父类的,

@Resource查找bean
autowireResource()方法来查找

根据名字判断容器当中是否有一个名字为属性名字的bean(单例池或者是与之对应的BeanDefinition)如果找到了, 就返回了, 如果找不到, 再根据类型去找

如果@Resource(name="aaa")注解给了值, 说明是一定要注入name为aaa的bean, 所以需要找到这个bean, 找不到对应的就报错
如果只是field的名字不一样, 比如 A aaa, 那么就是说, 需要一个name为aaa的bean, 如果没有, 就去找一个类型为A的bean(这里的流程和@Autowired一样), 不是强制要name为aaa的bean

posted @   RichardHaha  阅读(32)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示