Spring框架@Autowired注解进行字段时,使用父类类型接收子类变量,可以注入成功吗?(@Autowired源码跟踪)
一、 前言
平常我们在使用spring框架开发项目过程中,会使用@Autowired注解进行属性依赖注入,一般我们都是声明接口类型来接收接口实现变量,那么使用父类类型接收子类变量,可以注入成功吗?答案是肯定可以的!
二、结果验证
我们在项目中声明如下三个类:
1. 测试代码
- TestParent
public class TestParent {protected void test() {System.out.println("I am TestParent...");}
}
- TestSon
importorg.springframework.stereotype.Component;@Component
public class TestSon extends TestParent {publicvoidtest() {System.out.println("I am TestSon...");}
}
- TestType
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.stereotype.Component;
importjavax.annotation.PostConstruct;@Component
public class TestType {@Autowiredprivate TestParent testParent;@PostConstructpublicvoidinit() {System.out.println("=========================");testParent.test();System.out.println("=========================");}
}
2. 验证测试
启动项目:

可以看到注入成功了,说明依赖注入使用父类类型接收子类变量是没有问题的。
3. @Autowired注解使用细节
还是上面的案例,我们修改一下TestParent类的代码,把TestParent也交由Spring容器管理:
importorg.springframework.stereotype.Component;@Component
public class TestParent {protected void test() {System.out.println("I am TestParent...");}
}
运行测试:

可以发现,此时也可以注入成功,但是执行对象变成了父类,有经验的大佬已经猜到是什么情况了,没猜到的也没有关系,我们再修改一下TestType类的代码:
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.stereotype.Component;
importjavax.annotation.PostConstruct;@Component
public class TestType {@Autowiredprivate TestParent test;@PostConstructpublic void init() {System.out.println("=========================");test.test();System.out.println("=========================");}
运行结果:

此时居然注入报错了,提示我们有两个bean冲突了,不能进行依赖注入!
三、原理分析
为什么会出现上面的现象呢,是由于@Autowired注入时,是先按照类型找到bean实例名称,再按照beanName去获取真正需要注入的bean,如果有多个实例时,会尝试通过需要注入的字段名称与按照类型筛选出来的beanName对比,如果能够对比出唯一beanName,也会按照此beanName去获取bean实例注入,如果不能够确定唯一bean实例,就会抛出异常了。
下面我们进行源码跟踪:
@Autowired注解解析的核心逻辑入口在org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor后置处理器中,我们进入该类中进行断点调试。
通过阅读源码我们可以发现,依赖注入入口方法是postProcessProperties()方法:

进入org.springframework.beans.factory.annotation.InjectionMetadata#inject方法:

继续调试,由于我们目前是字段方式注入,所以选择org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement类:

查看方法细节:

我们继续跟踪org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#resolveFieldValue方法:

进入org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveDependency方法:

继续进入org.springframework.beans.factory.support.DefaultListableBeanFactory#doResolveDependency方法:

继续进入org.springframework.beans.factory.support.DefaultListableBeanFactory#findAutowireCandidates方法:

进入org.springframework.beans.factory.BeanFactoryUtils#beanNamesForTypeIncludingAncestors(org.springframework.beans.factory.ListableBeanFactory, java.lang.Class, boolean, boolean)看一下bean的筛选逻辑:

跟踪进入org.springframework.beans.factory.support.DefaultListableBeanFactory#doGetBeanNamesForType方法:

查看类型匹配判断方法org.springframework.beans.factory.support.AbstractBeanFactory#isTypeMatch(java.lang.String, org.springframework.core.ResolvableType, boolean):

判断核心方法org.springframework.core.ResolvableType#isInstance:

看到isAssignableFrom方法就知道为什么子类变量也可以成功注入父类类型了,此时子类变量也是可以成功匹配上的。
筛选出所有类型匹配的beanName以后,回到org.springframework.beans.factory.support.DefaultListableBeanFactory#findAutowireCandidates做一下是否可以进行依赖注入的判断,返回beanName信息:

然后回到org.springframework.beans.factory.support.DefaultListableBeanFactory#doResolveDependency方法中,如果有多个类型,会按照字段名称和beanName匹配再筛选:

最终确定获取到可以注入的bean实例。
四、写在最后
以上流程还是比较清晰的,分析过程中有一些分支流程没有过度关注,有兴趣的小伙伴也可以参考流程,自己进行debug调试分析。
相关文章:
Spring框架@Autowired注解进行字段时,使用父类类型接收子类变量,可以注入成功吗?(@Autowired源码跟踪)
一、 前言 平常我们在使用spring框架开发项目过程中,会使用Autowired注解进行属性依赖注入,一般我们都是声明接口类型来接收接口实现变量,那么使用父类类型接收子类变量,可以注入成功吗?答案是肯定可以的!…...
【springblade】springblade(bladeX) 数据权限失效原因分析
文章目录 数据权限接口权限 前言:最近博主在按照bladeX官方文档 配置数据权限 结果发现失效了,网上搜了一下没找到合适的答案,本着求人不如求己的精神,自己调试了一下发现了问题所在,也大致看了一下bladeX的权限逻辑。…...
单例模式的几种实现方式
在Java中,实现单例模式主要有几种方式:懒汉式、饿汉式、双重检查锁定、静态内部类和枚举。每种方式都有其特点和适用场景。 1. 饿汉式(线程安全) 饿汉式是最简单的一种实现方式,通过静态初始化实例,保证了…...
鸿蒙OS运行报错 ‘ToDoListItem({ item })‘ does not meet UI component syntax.
在学习harmonyOS时,原本是好好运行的。但是突然报错 ToDoListItem({ item }) does not meet UI component syntax. 一脸懵逼,以为是自己语法问题检查了半天也没问题。 网上搜索了一下,说把多余的js\map文件删除就行 才发现我的 鸿蒙的开…...
React18源码: reconciler执行流程
reconciler执行流程 1 )概述 此处先归纳一下react-reconciler包的主要作用,将主要功能分为4个方面: 输入:暴露api函数(如:scheduleUpdateOnFiber), 供给其他包(如react包࿰…...
mapbox面图层标注
mapbox并没有一个属性类似于’text-field’的symbol图层的直接可以标注的办法,这里笔者提供两种其他的面图层标注的办法用来大家参考 效果图 方案一 把面图层当做点图层直接展示 在mapbox里面,面图层是可以直接渲染成线图层和点图层的,这里…...
MySQL|MySQL基础(求知讲堂-学习笔记【详】)
MySQL基础 目录 MySQL基础一、 MySQL的结构二、 管理数据库1)查询所有的数据库2)创建数据库3)修改数据库的字符编码4)删除数据库5)切换操作的数据库 三、表的概念四、字段的数据类型4.1 整型4.2 浮点型(float和double)…...
10.docker exec -it /bin/bash报错解决、sh与bash区别
报错 进入容器时,报如下错误 dockeruserdell-PowerEdge-R740:~$ docker exec -it daf2 /bin/bash OCI runtime exec failed: exec failed: unable to start container process: exec: "/bin/bash": stat /bin/bash: no such file or directory: unknown…...
查询数据库的编码集Oracle,MySQL
1、查询数据库的编码集Oracle,MySQL 1.1、oracle select * from v$nls_parameters where parameterNLS_CHARACTERSET; 查询版本:SELECT * FROM v$version 2、MySQL编码集 SELECT DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME FROM information_schema.SC…...
电商数据采集+跨境电商|API电商数据采集接口洞悉数字新零售发展
随着全球经济一体化和电子商务的快速发展,网络购物的需求日益增加。不断涌现的电商企业使得行业的竞争情况愈演愈烈。在这种情况下,企业不仅要加大经营力度,还要在自己的基础设施和技术上持续投入,才能更好的适应市场和消费习惯。…...
linux之用户和用户组
文章目录 一、简介1.1 用户1.2 用户组1.3 UID和GID1.4 用户账户分类 二、用户2.1 添加新的用户账号:useradd2.2 删除账号:userdel2.3 修改账号:usermod(modmodify)2.4 用户口令的管理:passwd2.5 切换用户:su 三、用户组3.1 增加一…...
人工智能深度学习
目录 人工智能 深度学习 机器学习 神经网络 机器学习的范围 模式识别 数据挖掘 统计学习 计算机视觉 语音识别 自然语言处理 机器学习的方法 回归算法 神经网络 SVM(支持向量机) 聚类算法 降维算法 推荐算法 其他 机器学习的分类 机器…...
python reshape 和 transpose的区别
reshape() 和 transpose() 是用于改变数组或张量形状的两种不同方法, 它们的主要区别在于如何重新排列元素以及是否可以改变轴的顺序。 1 reshape() reshape() 函数用于改变数组或张量的形状,但是不改变元素的排列顺序。它只是简单地将数组的维度重新…...
音视频技术-网络视频会议“回声”的消除
目录 一、“回音”的成因原理 二、解决思路 三、解决方案 1、方案一 2...
有哪些令人惊讶的心理学效应
大家可以想象一个场景: 如果一次考试,你考了95分,比上次还进步了10分,你会感到高兴吗? 听起来很牛逼啊,值得干杯庆祝,好好开心几天了。 这时,你看到同桌这次居然是一百分…...
二叉树基础知识总结
目录 二叉树基础知识 概念 : 根节点的五个形态 : 特殊的二叉树 满二叉树 : 完全二叉树 : 二叉搜索树 : 平衡二叉搜索树 : 二叉树的性质 : 二叉树的存储结构 二叉树的顺序存储结构 二叉树的链式存储结构 二叉树的遍历方式 : 基础概念 前中后遍历 层序遍历 :…...
IDEA2023.3.4开启SpringBoot项目的热部署【简单明了4步操作】
添加devtools依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional> </dependency>IDEA开启自动编译 …...
QT中调用python
一.概述 1.Python功能强大,很多Qt或者c/c开发不方便的功能可以由Python编码开发,尤其是一些算法库的应用上,然后Qt调用Python。 2.在Qt调用Python的过程中,必须要安装python环境,并且Qt Creator中编译器与Python的版…...
Sora基础知识学习
...
开源博客项目Blog .NET Core源码学习(9:Autofac使用浅析)
开源博客项目Blog使用Autofac注册并管理组件和服务,Autofac是面向.net 的开源IOC容器,支持通过接口、实例、程序集等方式注册组件和服务,同时支持属性注入、方法注入等注入方式。本文学习并记录Blog项目中Autofac的使用方式。 整个Blog解…...
[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解
突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 安全措施依赖问题 GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...
Java如何权衡是使用无序的数组还是有序的数组
在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...
《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...
【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...
如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...
GC1808高性能24位立体声音频ADC芯片解析
1. 芯片概述 GC1808是一款24位立体声音频模数转换器(ADC),支持8kHz~96kHz采样率,集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器,适用于高保真音频采集场景。 2. 核心特性 高精度:24位分辨率,…...
JAVA后端开发——多租户
数据隔离是多租户系统中的核心概念,确保一个租户(在这个系统中可能是一个公司或一个独立的客户)的数据对其他租户是不可见的。在 RuoYi 框架(您当前项目所使用的基础框架)中,这通常是通过在数据表中增加一个…...
LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》
这段 Python 代码是一个完整的 知识库数据库操作模块,用于对本地知识库系统中的知识库进行增删改查(CRUD)操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 📘 一、整体功能概述 该模块…...
站群服务器的应用场景都有哪些?
站群服务器主要是为了多个网站的托管和管理所设计的,可以通过集中管理和高效资源的分配,来支持多个独立的网站同时运行,让每一个网站都可以分配到独立的IP地址,避免出现IP关联的风险,用户还可以通过控制面板进行管理功…...
jmeter聚合报告中参数详解
sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample(样本数) 表示测试中发送的请求数量,即测试执行了多少次请求。 单位,以个或者次数表示。 示例:…...
