深入剖析Spring框架:推断构造方法与@Bean注解的内部机制

你好,我是柳岸花开。

Spring框架作为Java开发中广泛使用的基础架构,其设计精巧、功能强大,尤其是其依赖注入(DI)和控制反转(IoC)特性,极大地提高了代码的可维护性和可测试性。本文将深入探讨Spring中的推断构造方法和@Bean注解的内部机制,帮助读者更深入地理解Spring框架。

推断构造方法

在Spring框架中,当我们定义一个Bean时,Spring容器需要根据类中的构造方法来实例化Bean。如果类中只有一个无参构造方法,Spring容器将使用它来创建实例。然而,当存在多个构造方法时,Spring将如何决定使用哪一个构造方法呢?

构造方法的选择

Spring提供了多种方式来指定使用哪个构造方法:

  1. 无参构造方法:如果没有其他指定,Spring默认使用无参构造方法。
  2. @Autowired注解:可以标记在构造方法上,指示Spring使用该构造方法,并根据参数类型自动注入依赖。
  3. **@Autowired(required=false)**:当标记在构造方法上时,即使没有匹配的Bean,Spring也不会抛出异常。
  4. XML配置:在XML中可以通过标签指定构造方法参数,或者使用 autowire="constructor"让Spring自动寻找Bean作为构造方法参数。

源码解析

Spring容器在创建Bean实例时,会调用AbstractAutowireCapableBeanFactory类的createBeanInstance()方法。该方法首先检查BeanDefinition是否绑定了Supplier,或者是否存在工厂方法名。如果这些条件都不满足,Spring将尝试自动构造Bean,即调用autowireConstructor()方法。 在autowireConstructor()方法中,Spring会检查是否指定了具体的构造方法或构造方法参数值。如果没有,它将找出所有可用的构造方法,并根据参数个数进行排序,优先选择参数个数最多的构造方法。然后,Spring会遍历每个构造方法,根据参数类型寻找匹配的Bean。如果找到匹配的构造方法,Spring将计算一个匹配分数,以确定最佳匹配。

@Bean注解

@Bean注解允许开发者以编程方式定义Bean的创建过程。Spring容器会将@Bean注解的方法解析成BeanDefinition,并在启动时调用这些方法来创建Bean。

@Bean与工厂方法

当使用@Bean注解时,Spring会考虑以下几点:

  1. 静态方法:如果 @Bean注解的方法是静态的,Spring会直接调用该方法获取Bean实例。
  2. 非静态方法:如果方法不是静态的,Spring会为该方法创建一个实例,然后调用它来获取Bean实例。
  3. 方法重载:如果存在重载,Spring会根据方法名和参数类型来确定使用哪个方法。

isFactoryMethodUnique属性

在由@Bean生成的BeanDefinition中,有一个重要的属性isFactoryMethodUnique,它表示工厂方法是否唯一。在大多数情况下,@Bean生成的BeanDefinitionisFactoryMethodUniquetrue。但如果出现方法重载,Spring会根据方法名和参数类型来确定使用哪个方法,并可能将isFactoryMethodUnique设置为false

实例化过程

在实例化Bean时,如果isFactoryMethodUniquetrue,Spring将直接使用对应的方法来创建Bean。如果为false,Spring将寻找所有匹配的方法,并根据参数类型和数量进行排序,选择最合适的方法来创建Bean。

 @Bean
 public static AService aService(){
  return new AService();
 }

 @Bean
 public AService aService(BService bService){
  return new AService();
 }

虽然有两个@Bean,但是肯定只会生成一个aService的Bean,那么Spring在处理@Bean时,也只会生成一个aService的BeanDefinition,比如Spring先解析到第一个@Bean,会生成一个BeanDefinition,此时isFactoryMethodUnique为true,但是解析到第二个@Bean时,会判断出来beanDefinitionMap中已经存在一个aService的BeanDefinition了,那么会把之前的这个BeanDefinition的isFactoryMethodUnique修改为false,并且不会生成新的BeanDefinition了。

并且后续在根据BeanDefinition创建Bean时,会根据isFactoryMethodUnique来操作,如果为true,那就表示当前BeanDefinition只对应了一个方法,那也就是只能用这个方法来创建Bean了,但是如果isFactoryMethodUnique为false,那就表示当前BeanDefition对应了多个方法,需要和推断构造方法的逻辑一样,去选择用哪个方法来创建Bean。

总结

本文深入探讨了Spring框架中推断构造方法和@Bean注解的内部机制。通过理解这些机制,我们可以更灵活地使用Spring框架,编写出更加健壮和灵活的应用程序。在下一节课中,我们将继续探索Spring的启动过程,揭示更多关于Spring IoC容器的内部工作机制。

结语

深入理解Spring框架的核心特性对于Java开发者来说非常重要。希望本文能够帮助读者更好地理解Spring的工作原理,并在实际开发中更加得心应手。如果你对Spring框架或者其他技术话题有任何疑问,欢迎在评论区交流讨论。让我们一起进步,探索技术的无限可能。

以上就是对Spring框架中推断构造方法和@Bean注解的深度解析。在下一节公众号文章中,我们将继续深入Spring框架的内部,探索更多令人兴奋的话题。敬请期待!

👇关注我,下期了解👇

Spring启动过程源码分析

alt

回复 222,获取Java面试题合集

关于我

一枚爱折腾的Java程序猿,专注Spring干货。把路上的问题记录下来,帮助那些和我一样的人。

好奇心强,喜欢并深入研究古天文。

崇尚 个人系统创建,做一些时间越长越有价值的事情。思考把时间留下来。

本文由 mdnice 多平台发布

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/833059.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

应用层协议——HTTP协议

1. 认识HTTP协议 HTTP(Hyper Text Transfer Protocol)协议又叫做超文本传输协议,是一个简单的请求-响应协议,HTTP通常运行在TCP之上。 超文本的意思就是超越普通的文本,http允许传送文字,图片&#xff0c…

嵌入式学习——C语言基础——day15

1. 段错误调试 1.1 打印法 在可能出现错误的位置加入打印,前一句能够打印出来,后一句打印不出来,问题就可以定位到两次打印中间的代码 1.2 gbd调试法 1. 编译代码时加入-g选项 gcc filename.c -g 2. 使用gdb调试生成的代码 gdb a.out 3. gdb调试命令 l 查看…

如何在已经安装好的PostgreSQL14中安装uuid 扩展

当前环境 PG14.8 LINUX 8.8 存在问题: 开发人员问,PG中,支持 生成UUID吗,具体是什么,答,类似这个函数 uuid_generate_v4() 看了一下, select uuid_generate_v4();会报错&#xff0…

C++之类与对象

1、类声明 2、共有、私有、保护成员。(就比如说你一个变量是private的,然后在main函数中,就调用不了,只能在这个类.cpp中调用) 3、数据抽象和封装 4、内联函数 内存体积会增大,以空间换时间:编…

CRM定义是什么?

CRM,即客户关系管理,是一种综合性的管理策略,旨在通过一系列技术手段和业务流程,建立、维护和优化企业与客户之间的关系。它不仅仅是一种技术工具,更是一种以客户为中心商业哲学,是现代企业提升竞争力、实现…

Redis中,hash的使用

在 Redis 中,键(Key)和哈希(Hash)是两种不同的数据结构,它们有以下主要区别: 1. **数据结构**: - **键(Key)**:Redis 的基本数据单元,…

【极速前进】20240423-20240428:Phi-3、fDPO、TextSquare多模态合成数据、遵循准则而不是偏好标签、混合LoRA专家

一、Phi-3技术报告 论文地址:https://arxiv.org/pdf/2404.14219 ​ 发布了phi-3-mini,一个在3.3T token上训练的3.8B模型。在学术基准和内部测试中的效果都优于Mixtral 8*7B和GPT-3.5。此外,还发布了7B和14B模型phi-3-small和phi-3-medium。…

golang testing使用

testing包服务于自动化测试 基本测试 Table Drvien Test 基于表的测试通过表形式进行测试每种情况的输入和期望输出,从而测试程序的正确性 func TestFib(t *testing.T) {var fibTests []struct {in int // inputexpected int // expected result}{{1, 1}…

字节和旷视提出HiDiffusion,无需训练,只需要一行代码就可以提高 SD 生成图像的清晰度和生成速度。代码已开源。

字节和旷视提出HiDiffusion,无需训练,只需要一行代码就可以提高 SD 生成图像的清晰度和生成速度。代码已开源。 支持将图像生成的分辨率提高至40964096,同时将图像生成速度提升1.5至6倍。 支持所有 SD 模型同时也支持 SD 模型的下游模型&…

事业单位与企业单位的区别

一、事业单位与企业单位区别 企业和事业单位的区别在于单位性质不同,企业单位是以盈利为目的的法人或非法人单位,事业单位是以政府职能和公益服务为宗旨的公益性单位或非公益性职能部门。事业单位有事业编制,属于体制内,企业没有…

MySQL的视图、存储过程、触发器

视图 介绍 视图是一种虚拟存在的表。视图中的数据并不在数据库中实际存在,行和列数据来自定义视图的查询中使用的表,并且是在使用视图时动态生成的。通俗的讲,视图只保存了查询的SQL逻辑,不保存查询结果。所以我们在创建视图的时…

【硬件基础概念】ADC与DAC

文章目录 前言一、模拟信号与数字信号1.1 模拟信号1.2 数字信号 二、ADC与DAC2.1 ADC2.2 DAC 总结 前言 在数字电子系统中,ADC(模数转换器)和DAC(数字模拟转换器)是两个至关重要的组件。ADC负责将来自外部世界的模拟信…

重装win11系统后找不到WiFi

由于电脑崩溃重装了系统,win11,装完之后WiFi图标不见了且网络适配器根本没有无线网络选项。 右键电脑》管理》网络适配器。 在刚装好系统时候并没有前两项,查了很多资料,比如 关机14s 重启,还有通过服务配置 WLAN AutoConfig 都…

windows 双网卡同时接入内外网

在公司使用wifi接入使用桌面云,但是公司wifi不能上外网,查资料不方便,通过手机同时接入外网。 同一台电脑设置同时连接内外网(wifi或共享的网络)_win7电脑同时使用手机和usb网卡使用wifi-CSDN博客 route print查看当前…

纯血鸿蒙APP实战开发——折叠屏扫描二维码方案

折叠屏扫描二维码方案 介绍 本示例介绍使用自定义界面扫码能力在折叠屏设备中实现折叠态切换适配。自定义界面扫码使用系统能力customScan,其提供相机流的初始化、启动扫码、识别、停止扫码、释放相机流资源等能力。折叠屏折叠状态通过监听display的foldStatusCha…

【网络编程】http协议

预备知识 什么是http协议 HTTP(Hypertext Transfer Protocol,超文本传输协议)是一个应用层的协议,用于在网络中传输超文本(如HTML文档)。HTTP协议建立在TCP/IP协议之上,是Web浏览器和Web服务器…

Redis学习6——Redis分布式锁

引言 分布式锁 分布式锁(Distributed Lock)是一种用于分布式系统中实现互斥访问的机制,在分布式系统中,多个节点同时访问共享资源可能导致数据不一致或竞态条件的问题,分布式锁通过协调多个节点之间的访问&#xff0…

运动控制“MC_MoveVelocity“功能块详细应用介绍

1、运动控制单位u/s介绍 运动控制单位[u/s]介绍-CSDN博客文章浏览阅读91次。运动控制很多手册上会写这样的单位,这里的u是英文单词unit的缩写,也就是单位的意思,所以这里的单位不是微米/秒,也不是毫米/秒,这里是一个泛指,当我们的单位选择脉冲时,它就是脉冲/秒,也就是…

QT creator5.0转qt6.0(QAbstractSocket::SocketError)‘ is not allowed解决方法

问题描述: //tcp_client.cpp:19:23: Static_cast from SocketError (QAbstractSocket::*)() const to void (QTcpSocket::*) //(QAbstractSocket::SocketError) is not allowed 原因分析: QtNetwork中的错误信号error换成了errorOccurred QT5.0 con…

懒人网址导航源码v3.9源码及教程

懒人网址导航源码v3.9源码及教程 效果图使用方法部分源码领取源码下期更新预报 效果图 使用方法 测试环境 宝塔Nginx -Tengine2.2.3的PHP5.6 MySQL5.6.44为防止调试错误,建议使用测试环境运行的php与mysql版本首先用phpMyAdmin导入数据库文件db/db.sql 如果导入不…