一. 找到所有被@Autowired、@Value、@Inject(若项目中有引入)注解的字段和方法
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
-
判断是否能从缓存中获取到,获取到并且类型匹配则直接返回
-
根据当前bean的class类型,获取所有的注入点
- 判断是否有@Autowired、@Value、@Inject注解
- 字段处理,获取required值(是否必须注入),static的属性不注入
- 方法处理,判断是否有@Required注解,static的方法不注入
- 可以成为注入点的字段或方法,封装为AutowiredFieldElement对象,放到List集合
对象里面封装了传入的对象(Field或者Method)和required属性(是否必须注入)
- 循环体最后获取当前目标class对象的父class,循环处理,直至Object.class停止
- 将所有筛选过后的注入点的集合,封装到InjectionMetadata对象中
- 返回
二. 根据返回的注入点,进行循环处理、注入
metadata.inject(bean, beanName, pvs);
element.inject(target, beanName, pvs);
- 判断是否能从缓存中获取到,获取到则通过反射set,返回
- 将字段描述以及required值 封装到DependencyDescriptor对象中
- 寻找是否有合适的bean
核心代码:
Object value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
Object result = doResolveDependency(descriptorToUse, beanName, null, null);
-
3.1 如果是Optional类型,封装起来,调用doResolveDependency进行解析(同下3.3)
-
3.2 如果是ObjectFactory类型,通过每次调用getObject方法,来装配字段属性,方法内也是调用了doResolveDependency进行解析(同下第3点)
-
3.3 解析字段类型 (★★★★实际工作原理/步骤★★★★,核心1—6点)
-
是否加了@Value注解
① 填充并解析“$”占位符
② 解析Spring EL表达式 #
③ 判断是否有合适的类型转换器
④ 返回
-
根据Type去获取,如果找到一个,判断如果是class,getBean,返回(获取多个,首先把自己排除掉,如果找不到,再把自己作为候选者装配进去,往下走)
-
拿到存有多个候选者的Map
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor); -
判断是否有@Primary注解(取到唯一,返回)
-
判断是否有@Priority注解(取到唯一,返回)
-
根据字段名或者方法名字匹配(取到唯一,返回)
-
如果还是不能确定唯一,required==true或字段不是集合、数组、Map类型 , 报错
-
拿到唯一的候选者,判断如果是class,getBean,返回
PS:
1.为什么拿到的候选者有可能是class?
答:因为取到的时候,这个参数bean可能还没有被实例化
2.Optional和ObjectFactory
答:Optional通过get()方法获取对象,如果被注入类型为原型,也只会返回同一个对象
ObjectFactory通过getObject()方法获取对象,如果被注入类型为原型,每次都会返回一个新对象,且每次是在getObject时才生成 -