Spring @Autowire注解源码详解
创始人
2024-03-22 13:10:12
0

目录

一:触发方式:

二:源码解析

2.1 扫描注入点

2.2 属性赋值


一:触发方式:

1.Spring容器在每个Bean实例化之后,调用AutowireAnnotationBeanPostProcessor的postProcessMergedBeanDefinition方法进行扫描注入点

2.Spring在每个Bean实例化之后,扫描完注入点之后,调用populateBean进行Bean注入,调用postProcessPropertyValues方法

二:源码解析

2.1 扫描注入点

通过在属性、构造方法、set方法上添加@Autowire注解可以将Bean进行依赖注入。

package service;import org.springframework.beans.factory.annotation.Autowired;public class UserService1 {@Autowiredprivate  OrderService orderService;public void test(){System.out.println(orderService);}}

首先先查找注入点,在创建Bean时,实例化后,调用

AbstractAutowireCapableBeanFactory.javaprotected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {....if (!mbd.postProcessed) {try {//todo 在实例化后,对MergeBeanDefinition进行属性修改applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);}catch (Throwable ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Post-processing of merged bean definition failed", ex);}mbd.postProcessed = true;}..}

进入applyMergedBeanDefinitionPostProcessors方法中,调用processor.postProcessMergedBeanDefinition(mbd,beanType,beanName);

	protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class beanType, String beanName) {for (MergedBeanDefinitionPostProcessor processor : getBeanPostProcessorCache().mergedDefinition) {processor.postProcessMergedBeanDefinition(mbd, beanType, beanName);}}

处理@Autowire注解的类时AutowiredAnnotationBeanPostProcessor

 进入findAutowiringMetadata(beanName,beanType,null);

 

buildAutowiringMetadata(final Class clazz) 方法中,循环遍历属性和循环遍历方法

,其中属性和方法不能是静态的 ,将field和required封装成一个AutowireFieldElement的一项,加入到currElements,最后合并成elements 

 

以上就是依赖注入寻找注入点的过程,还没进行属性赋值

2.2 属性赋值

在Bean的实例化之后,进行循环依赖、属性填充、初始化、销毁bean。

进入到 populateBean(beanName, mbd, instanceWrapper);

主要根据postProcessProperties 进行属性注入

在这里找注入点、属性赋值。查找注入点上面分析过,下面分析属性赋值。

 @Autowire注解加在field上的inject()方法在AutowiredFieldElement内部类中

 第一次没有缓存进入到resolveFieldValue(field,bean,beanName)中,缓存针对于原型bean,因为单例bean只会创建一次,属性也是注入一次。

最终在DefaultListableBeanFactory.java中 将bean找到返回

1.首先处理@Value注解

2.判断是不是Map、List复杂Bean,其中还是调用findAutowireCandidates方法,根据类型去Spring容器中去找

Map matchingBeans = findAutowireCandidates(beanName, valueType,new MultiElementDescriptor(descriptor));

3.根据类型去Spring容器中找Bean,返回的key为beanName,value有可能是bean对象,有可能是bean class

Map matchingBeans = findAutowireCandidates(beanName, type, descriptor);

4.如果matcingbeans.size >1 根据类型找到多个bean时,再根据name去找,调用

determineAutowireCandidate 方法,先去判断有没有加@primary注解 ,如果有则返回这个bean,然后再判断这个bean的优先级,再匹配descriptor的名字,要么是字段的名字,要么是set方法入参的名字。最终返回这个beanName,如果这些注解都没有加则返回null。

5.如果第四步返回的bull,并且没有配置@Autowire(required=false) 并且 beans不是复杂类型,则抛异常  expected single matching bean but found beanName

6.根据beanName,获取bean /bean class 返回

 

相关内容

热门资讯

汽车油箱结构是什么(汽车油箱结... 本篇文章极速百科给大家谈谈汽车油箱结构是什么,以及汽车油箱结构原理图解对应的知识点,希望对各位有所帮...
美国2年期国债收益率上涨15个... 原标题:美国2年期国债收益率上涨15个基点 美国2年期国债收益率上涨15个基...
嵌入式 ADC使用手册完整版 ... 嵌入式 ADC使用手册完整版 (188977万字)💜&#...
重大消息战皇大厅开挂是真的吗... 您好:战皇大厅这款游戏可以开挂,确实是有挂的,需要了解加客服微信【8435338】很多玩家在这款游戏...
盘点十款牵手跑胡子为什么一直... 您好:牵手跑胡子这款游戏可以开挂,确实是有挂的,需要了解加客服微信【8435338】很多玩家在这款游...
senator香烟多少一盒(s... 今天给各位分享senator香烟多少一盒的知识,其中也会对sevebstars香烟进行解释,如果能碰...
终于懂了新荣耀斗牛真的有挂吗... 您好:新荣耀斗牛这款游戏可以开挂,确实是有挂的,需要了解加客服微信8435338】很多玩家在这款游戏...
盘点十款明星麻将到底有没有挂... 您好:明星麻将这款游戏可以开挂,确实是有挂的,需要了解加客服微信【5848499】很多玩家在这款游戏...
总结文章“新道游棋牌有透视挂吗... 您好:新道游棋牌这款游戏可以开挂,确实是有挂的,需要了解加客服微信【7682267】很多玩家在这款游...
终于懂了手机麻将到底有没有挂... 您好:手机麻将这款游戏可以开挂,确实是有挂的,需要了解加客服微信【8435338】很多玩家在这款游戏...