当前位置: 首页 > news >正文

【Spring】Spring之依赖注入源码解析

1 Spring注入方式

1.1 手动注入

xml中定义Bean,程序员手动给某个属性赋值。

  • set方式注入
<bean name="userService" class="com.firechou.service.UserService"><property name="orderService" ref="orderService"/>
</bean>
  • 构造方法注入
<bean name="userService" class="com.firechou.service.UserService"><constructor-arg index="0" ref="orderService"/>
</bean>

1.2 自动注入

1.2.1 XML的autowire自动注入

<bean id="userService" class="com.firechou.service.UserService" autowire="byType"/>

Spring会自动的给userService中所有的属性自动赋值(不需要这个属性上有@Autowired注解,但需要这个属性有对应的set方法);
XML的自动注入底层其实也就是set方法注入和构造方法注入;

Bean的自动注入模式autowire:

  • byType

获取到set方法中的唯一参数的参数类型,并且根据该类型去容器中获取bean,如果找到多个,会报错。

  • byName

找到所有set方法所对应的XXX部分的名字,根据XXX部分的名字去获取bean。

  • constructor

通过构造方法注入,可以不写set方法;
如果存在多个构造方法,则通过构造方法推断来选择某个构造方法;
Spring利用构造方法的参数信息从Spring容器中去找Bean,找到Bean之后作为参数传给构造方法,从而实例化得到一个bean对象,并完成属性赋值(属性赋值的代码得程序员来写);

  • default
  • no

关闭autowire

PropertyDescriptor:
创建Bean的过程中,填充属性时,Spring会去解析当前类,解析类中每个方法得到对应的PropertyDescriptor对象,PropertyDescriptor中有几个属性:

  1. name:这个name并不是方法的名字,而是拿方法名字进过处理后的名字
    1. 如果方法名字以“get”开头,比如“getXXX”,那么name=XXX
    2. 如果方法名字以“is”开头,比如“isXXX”,那么name=XXX
    3. 如果方法名字以“set”开头,比如“setXXX”,那么name=XXX
  2. readMethodRef:表示get方法的Method对象的引用
  3. readMethodName:表示get方法的名字
  4. writeMethodRef:表示set方法的Method对象的引用
  5. writeMethodName:表示set方法的名字
  6. propertyTypeRef:如果有get方法那么对应的就是返回值的类型,如果是set方法那么对应的就是set方法中唯一参数的类型

什么是set和get方法:

  • get方法定义

方法参数个数为0个,并且方法名字以"get"开头,或者方法名字以"is"开头并且方法的返回类型为boolean

  • set方法定义

方法参数个数为1个,并且方法名字以"set"开头并且方法返回类型为void

1.2.2 @Autowired注解的自动注入

@Autowired注解相当于XML中的autowire属性的注解方式的替代;
@Autowired注解提供了与XML中autowire相同的功能,但是拥有更细粒度的控制和更广泛的适用性
XML中的autowire控制的是整个bean的所有属性,而@Autowired注解是直接写在某个属性、某个set方法、某个构造方法上的;
如果一个类有多个构造方法,那么如果用XML的autowire=constructor,无法控制到底用哪个构造方法,可以用@Autowired注解来直接指定想用哪个构造方法;
@Autowired注解还可以控制,哪些属性想被自动注入,哪些属性不想,这也是细粒度的控制;
@Autowired无法区分byType和byName,@Autowired是先byType,如果找到多个则byName;

@Autowired注解可以写在:

  1. 属性上:先根据属性类型去找Bean,如果找到多个再根据属性名确定一个
  2. 构造方法上:先根据方法参数类型去找Bean,如果找到多个再根据参数名确定一个
  3. set方法上:先根据方法参数类型去找Bean,如果找到多个再根据参数名确定一个

2 寻找注入点

在创建一个Bean的过程中,Spring会利用AutowiredAnnotationBeanPostProcessor的**postProcessMergedBeanDefinition()**找出注入点并缓存。

找注入点的流程为:

  1. 遍历当前类的所有的属性字段Field
  2. 查看字段上是否存在@Autowired、@Value、@Inject中的其中任意一个,存在则认为该字段是一个注入点
  3. 如果字段是static的,则不进行注入
  4. 获取@Autowired中的required属性的值
  5. 将字段信息构造成一个AutowiredFieldElement对象,作为一个注入点对象添加到currElements集合中。
  6. 遍历当前类的所有方法Method
  7. 判断当前Method是否是桥接方法,如果是找到原方法
  8. 查看方法上是否存在@Autowired、@Value、@Inject中的其中任意一个,存在则认为该方法是一个注入点
  9. 如果方法是static的,则不进行注入
  10. 获取@Autowired中的required属性的值
  11. 将方法信息构造成一个AutowiredMethodElement对象,作为一个注入点对象添加到currElements集合中
  12. 遍历完当前类的字段和方法后,将遍历父类的,直到没有父类
  13. 最后将currElements集合封装成一个InjectionMetadata对象,作为当前Bean对于的注入点集合对象,并缓存

3 注入点进行注入

Spring在AutowiredAnnotationBeanPostProcessor的**postProcessProperties()**方法中,会遍历所找到的注入点依次进行注入。

字段注入:

  1. 遍历所有的AutowiredFieldElement对象。
  2. 将对应的字段封装为DependencyDescriptor对象
  3. 调用BeanFactory的resolveDependency()方法,传入DependencyDescriptor对象,进行依赖查找,找到当前字段所匹配的Bean对象。
  4. DependencyDescriptor对象和所找到的结果对象beanName封装成一个ShortcutDependencyDescriptor对象作为缓存,比如如果当前Bean是原型Bean,那么下次再来创建该Bean时,就可以直接拿缓存的结果对象beanName去BeanFactory中去那bean对象了,不用再次进行查找了
  5. 利用反射将结果对象赋值给字段。

Set方法注入:

  1. 遍历所有的AutowiredMethodElement对象
  2. 遍历将对应的方法的参数,将每个参数封装成MethodParameter对象
  3. MethodParameter对象封装为DependencyDescriptor对象
  4. 调用BeanFactory的resolveDependency()方法,传入DependencyDescriptor对象,进行依赖查找,找到当前方法参数所匹配的Bean对象。
  5. DependencyDescriptor对象和所找到的结果对象beanName封装成一个ShortcutDependencyDescriptor对象作为缓存,比如如果当前Bean是原型Bean,那么下次再来创建该Bean时,就可以直接拿缓存的结果对象beanName去BeanFactory中去那bean对象了,不用再次进行查找了
  6. 利用反射将找到的所有结果对象传给当前方法,并执行。

相关文章:

【Spring】Spring之依赖注入源码解析

1 Spring注入方式 1.1 手动注入 xml中定义Bean&#xff0c;程序员手动给某个属性赋值。 set方式注入 <bean name"userService" class"com.firechou.service.UserService"><property name"orderService" ref"orderService"…...

【微软知识】微软相关技术知识分享

微软技术领域 一、微软操作系统&#xff1a; 微软的操作系统主要是 Windows 系列&#xff0c;包括 Windows 10、Windows Server 等。了解 Windows 操作系统的基本使用、配置和故障排除是非常重要的。微软操作系统&#xff08;Microsoft System&#xff09;是美国微软开发的Wi…...

12.python设计模式【观察者模式】

内容&#xff1a;定义对象间的一种一对多的依赖关系&#xff0c;当一个对象的状态发生改变的时候&#xff0c;所有依赖于它的对象得到通知并被自动更新。观者者模式又称为“发布-订阅”模式。比如天气预报&#xff0c;气象局分发气象数据。 角色&#xff1a; 抽象主题&#xf…...

重生之我要学C++第五天

这篇文章主要内容是构造函数的初始化列表以及运算符重载在顺序表中的简单应用&#xff0c;运算符重载实现自定义类型的流插入流提取。希望对大家有所帮助&#xff0c;点赞收藏评论&#xff0c;支持一下吧&#xff01; 目录 构造函数进阶理解 1.内置类型成员在参数列表中的定义 …...

复习之linux高级存储管理

一、lvm----逻辑卷管理 1.lvm定义 LVM是 Logical Volume Manager&#xff08;逻辑卷管理&#xff09;的简写&#xff0c;它是Linux环境下对磁盘分区进行管理的一种机制。 逻辑卷管理器(LogicalVolumeManager)本质上是一个虚拟设备驱动&#xff0c;是在内核中块设备和物理设备…...

HuggingGPT Solving AI Tasks with ChatGPT and its Friends in Hugging Face

总述 HuggingGPT 让LLM发挥向路由器一样的作用&#xff0c;让LLM来选择调用那个专业的模型来执行任务。HuggingGPT搭建LLM和专业AI模型的桥梁。Language is a generic interface for LLMs to connect AI models 四个阶段 Task Planning&#xff1a; 将复杂的任务分解。但是这里…...

java工程重写jar包中class类覆盖问题

结论&#xff1a;直接在程序中复写jar中的类即可 原因&#xff1a;一般我java工程是运行在tomcat容器中&#xff0c;tomcat容易在加载我们工程类和jar包是的优先级为&#xff1a; 我们工程的class 先于 我们工程lib下的jar 重复的类只加载一次&#xff0c;加载我们复写后的类后…...

Mybatis基于注解与XML开发

文章目录 1 关于SpringBoot2 关于MyBatis2.1 MyBatis概述2.2 MyBatis核心思想2.3 MyBatis使用流程3 MyBatis配置SQL方式3.1 基于注解方式3.1.1 说明3.1.2 使用流程3.1.3 常用注解 3.2 基于XML方式3.2.1 相比注解优势3.2.2 使用流程3.2.3 常用标签 1 关于SpringBoot SpringBoot…...

数字化转型导师坚鹏:数字化时代扩大内需的8大具体建议

在日新月异的数字化时代、复杂多变的国际化环境下&#xff0c;扩大内需成为推动经济发展的国家战略&#xff0c;如何真正地扩大内需&#xff1f;结合本人15年的管理咨询经验及目前实际情况的深入研究&#xff0c;提出以下8大具体建议&#xff1a; 1、制定国民收入倍增计划。结…...

M1/M2 通过VM Fusion安装Win11 ARM,解决联网和文件传输

前言 最近新入了Macmini M2&#xff0c;但是以前的老电脑的虚拟机运行不起来了。&#x1f605;&#xff0c;实际上用过K8S的时候&#xff0c;会发现部分镜像也跑不起来&#xff0c;X86的架构和ARM实际上还是有很多隐形兼容问题。所以只能重新安装ARM Win11&#xff0c;幸好微软…...

Linux中显示系统正在运行的进程的命令

2023年7月29日&#xff0c;周六上午 在Linux中&#xff0c;ps命令用于显示当前系统中正在运行的进程&#xff0c; ps应该是processes snapshot&#xff08;进程快照&#xff09;的缩写。 以下是ps命令的常见用法和示例&#xff1a; 显示当前用户的所有进程&#xff1a;ps 显示…...

vite中安装less

使用vite创建的项目&#xff0c;默认是没有安装less的 如果直接在style中书写less 会报下图错误&#xff1a; 解决方案&#xff1a; npm install --save less 在package.json中查看是否安装成功 安装完成刷新页面&#xff0c;问题解决...

Aduino中eps环境搭建

这里只记录Arduino2.0以后版本&#xff1a;如果有外网环境&#xff0c;那么可以轻松搜到ESP32开发板环境并安装&#xff0c;如果没有&#xff0c;那就见下面操作&#xff1a; 进入首选项&#xff0c;将esp8266的国内镜像地址填入&#xff0c;然后保存&#xff0c;在开发板中查…...

python——案例二 求两个数的和

#案例二 求两个数的和 num1input(请输入第一个数字&#xff1a;) num2input(请输入第二个数字&#xff1a;) sumfloat(num1)float(num2) #计算公式 print(sum) #显示结果 输入num11、num22得到结果sum3...

一文了解 Android 车机如何处理中控的旋钮输入?

前言 上篇文章《从实体按键看 Android 车载的自定义事件机制》带大家了解了 Android 车机支持自定义输入的机制 CustomInputService。事实上&#xff0c;除了支持自定义事件&#xff0c;对于中控上常见的音量控制、焦点控制的旋钮事件&#xff0c;Android 车机也是支持的。 那…...

小红书推广 方法总结

大家好&#xff0c;我是网媒智星&#xff0c;今天跟大家分享一下小红书的推广方法和经验。 一、平台简介 1、什么是小红书&#xff1f; 小红书是一个消费决策/生活方式平台&#xff0c;用户可以通过图片、文案、视频等方式分享美好生活。 2、用户画像 - 2亿月活跃…...

通讯录的实现(超详细)——C语言(进阶)

目录 一、创建联系人信息&#xff08;结构体&#xff09; 二、创建通讯录&#xff08;结构体&#xff09; 三、define定义常量 四、打印通讯录菜单 五、枚举菜单选项 六、初始化通讯录 七、实现通讯的的功能 7.1 增加加联系人 7.2 显示所有联系人的信息 ​7.3 单独查…...

3D 渲染技巧-如何创建高质量写实渲染?

掌握创建高质量建筑渲染和任何 3D 渲染的艺术是一项复杂且需要技巧的工作&#xff0c;通常需要多年的经验和实践。实现逼真的结果需要仔细考虑众多因素&#xff0c;并避免可能导致缺乏真实性的假渲染效果的常见错误。 避免常见错误 - 提升渲染游戏的技巧 在追求创建真正逼真的…...

fastadmin采坑之获取当前登录admin用户的信息

在controller层里想要获取当前登录admin用户的信息 print_r($this->auth->getUserInfo());但是有个问题 我在fa_admin表中添加了新的字段&#xff0c;这个方法获取不到新字段的数值&#xff0c;具体也没有去研究估计跟方法有关 然后我直接用模型去获取数据&#xff0c;简…...

【Spring AOP + 自定义注解 + 动态数据源 实现主从库切换读写分离】—— 案例实战

&#x1f4a7; S p r i n g A O P 主从数据源切换 读写分离 自定义注解案例实战&#xff01; \color{#FF1493}{Spring AOP 主从数据源切换 读写分离 自定义注解 案例实战&#xff01;} SpringAOP主从数据源切换读写分离自定义注解案例实战&#xff01;&#x1f4a7; …...

Chapter03-Authentication vulnerabilities

文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

STM32F4基本定时器使用和原理详解

STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

cf2117E

原题链接&#xff1a;https://codeforces.com/contest/2117/problem/E 题目背景&#xff1a; 给定两个数组a,b&#xff0c;可以执行多次以下操作&#xff1a;选择 i (1 < i < n - 1)&#xff0c;并设置 或&#xff0c;也可以在执行上述操作前执行一次删除任意 和 。求…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)

笔记整理&#xff1a;刘治强&#xff0c;浙江大学硕士生&#xff0c;研究方向为知识图谱表示学习&#xff0c;大语言模型 论文链接&#xff1a;http://arxiv.org/abs/2407.16127 发表会议&#xff1a;ISWC 2024 1. 动机 传统的知识图谱补全&#xff08;KGC&#xff09;模型通过…...

k8s业务程序联调工具-KtConnect

概述 原理 工具作用是建立了一个从本地到集群的单向VPN&#xff0c;根据VPN原理&#xff0c;打通两个内网必然需要借助一个公共中继节点&#xff0c;ktconnect工具巧妙的利用k8s原生的portforward能力&#xff0c;简化了建立连接的过程&#xff0c;apiserver间接起到了中继节…...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南

文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/55aefaea8a9f477e86d065227851fe3d.pn…...

云原生玩法三问:构建自定义开发环境

云原生玩法三问&#xff1a;构建自定义开发环境 引言 临时运维一个古董项目&#xff0c;无文档&#xff0c;无环境&#xff0c;无交接人&#xff0c;俗称三无。 运行设备的环境老&#xff0c;本地环境版本高&#xff0c;ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...

LCTF液晶可调谐滤波器在多光谱相机捕捉无人机目标检测中的作用

中达瑞和自2005年成立以来&#xff0c;一直在光谱成像领域深度钻研和发展&#xff0c;始终致力于研发高性能、高可靠性的光谱成像相机&#xff0c;为科研院校提供更优的产品和服务。在《低空背景下无人机目标的光谱特征研究及目标检测应用》这篇论文中提到中达瑞和 LCTF 作为多…...

mac:大模型系列测试

0 MAC 前几天经过学生优惠以及国补17K入手了mac studio,然后这两天亲自测试其模型行运用能力如何&#xff0c;是否支持微调、推理速度等能力。下面进入正文。 1 mac 与 unsloth 按照下面的进行安装以及测试&#xff0c;是可以跑通文章里面的代码。训练速度也是很快的。 注意…...