@Autowired与@Value注解工作原理

it2025-09-06  16

一. 找到所有被@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时才生成

最新回复(0)