Spring @Autowire注解源码详解
目录
一:触发方式:
二:源码解析
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<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType,new MultiElementDescriptor(descriptor));
3.根据类型去Spring容器中找Bean,返回的key为beanName,value有可能是bean对象,有可能是bean class
Map<String, Object> 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 返回
Spring @Autowire注解源码详解相关推荐
- 【JAVA秘籍心法篇-Spring】Spring XML解析源码详解
[JAVA秘籍心法篇-Spring]Spring XML解析源码详解 所谓天下武功,无坚不摧,唯快不破.但有又太极拳法以快制慢,以柔克刚.武功外式有拳打脚踢,刀剑棍棒,又有内功易筋经九阳神功.所有外功 ...
- Spring事务源码详解
一. 简介 事务: 事务是逻辑上的一组操作,要么都执行,要么都不执行,关于事务的基本知识可以看我的这篇文章:事务的基础知识 Spring事务: Spring 支持两种方式的事务管理:编程式事务管理.声 ...
- 封装成jar包_通用源码阅读指导mybatis源码详解:io包
io包 io包即输入/输出包,负责完成 MyBatis中与输入/输出相关的操作. 说到输入/输出,首先想到的就是对磁盘文件的读写.在 MyBatis的工作中,与磁盘文件的交互主要是对 xml配置文件的 ...
- 【Live555】live555源码详解(九):ServerMediaSession、ServerMediaSubsession、live555MediaServer
[Live555]live555源码详解系列笔记 继承协作关系图 下面红色表示本博客将要介绍的三个类所在的位置: ServerMediaSession.ServerMediaSubsession.Dy ...
- 【Live555】live555源码详解系列笔记
[Live555]liveMedia下载.配置.编译.安装.基本概念 [Live555]live555源码详解(一):BasicUsageEnvironment.UsageEnvironment [L ...
- 【Live555】live555源码详解(八):testRTSPClient
[Live555]live555源码详解系列笔记 继承协作关系图 下面红色表示本博客将要介绍的testRTSPClient实现的三个类所在的位置: ourRTSPClient.StreamClient ...
- 【Live555】live555源码详解(七):GenericMediaServer、RTSPServer、RTSPClient
[Live555]live555源码详解系列笔记 继承协作关系图 下面红色表示本博客将要介绍的三个类所在的位置: GenericMediaServer.RTSPServer.RTSPClient 14 ...
- 【Live555】live555源码详解(六):FramedSource、RTPSource、RTPSink
[Live555]live555源码详解系列笔记 继承协作关系图 下面红色表示本博客将要介绍的三个类所在的位置: FramedSource.RTPSource.RTPSink 11.FramedSou ...
- 【Live555】live555源码详解(五):MediaSource、MediaSink、MediaSession、MediaSubsession
[Live555]live555源码详解系列笔记 继承协作关系图 下面红色表示本博客将要介绍的四个类所在的位置: MediaSource.MediaSink.MediaSession.MediaSub ...
最新文章
- 用Linux构建高效FTP服务器(2)
- python知识点 07-11
- 独家专访 | 红布林(Plum​)庞博:万亿元二手时尚交易蓝海的生存法则
- android:persistent (非系统app失效)
- Listener refused the connection with the following error 错误解决(最大连接数)
- springboot+flowable第四节(设置监听事件)
- Linux USB驱动框架分析
- python-学生管理系统--3删除学生信息功能
- 禁止浏览器记录 文本框之前输入过的内容
- vue3 实现的砸金蛋
- java openoffic excel转html,Java利用OpenOffice進行將word,excel轉化成html解析到界面(上)...
- Android校招复习资料整理
- 模拟电路9(微变等效电路法对共射基本放大电路进行分析)
- bittorrent_面向初学者的BitTorrent:充分利用Internet连接
- 应届毕业生找Python工作遇到的难题,刚毕业没有工作经验该怎么办?
- 金属学复习【1】金属的晶体结构
- html如何制作美观搜索栏,css制作好看的搜索框
- 通过和resnet18和resnet50理解PyTorch的ResNet模块
- 如何在Python中获取图片分辨率?——Python实现获取图片分辨率的代码及详解。
- 基于百度英伟达EasyDL公开课的学习笔记
热门文章
- 营业执照正本与副本的区别
- 最好的数据恢复软件应该具备深度恢复技术
- 安卓实现天天动听音乐播放歌词悬浮哦(转)
- Android BitmapShader实现圆角、圆形ImageView
- 查询CNAPS 代码
- 分解变频电源的原理性
- macbook 关于微信突然打开白屏
- 【GNN】应用场景总结
- 微信测试账户的申请,以及配置失败问题的处理,最新
- android打包报错 AAPT: error: IDAT: incorrect data check. AAPT: error: file failed to compile.