详解Spring IoCDI(二)
目录
承接上文:详解Spring IoC&DI (一)
1.IoC详解
1.1方法注解@Bean
1.2方法注解要配合类注解使用
1.3定义多个对象
1.4重命名Bean
1.5扫描路径
2.DI详解
2.1DI与IoC的关系
2.2属性注入
2.3构造方法注入
2.4Setter注入
2.5 三种注入优缺点分析
2.6Autowired存在问题
2.6.1Primary
2.6.2Qualifier
2.6.3Resource
承接上文:详解Spring IoC&DI (一)
1.IoC详解
1.1方法注解@Bean
类注解是添加到某个类上的 , 但是存在两个问题:
1.使⽤外部包⾥的类, 没办法添加类注解
2.⼀个类, 需要多个对象, 比如多个数据源
这种场景, 我们就需要使⽤⽅法注解@Bean
代码示例:
public class BeanConfig { @Beanpublic User user(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;}}
当我们写完以上代码 ,尝试获取 bean 对象中的 user 时却发现 ,根本获取不到:
@SpringBootApplication
public class TestSpringTwoApplication {public static void main(String[] args) {ApplicationContext context = SpringApplication.run(TestSpringTwoApplication.class,args);//从Spring上下⽂中获取对象User user =context.getBean(User.class);//使⽤对象System.out.println(user);}
}
执行结果如下:

1.2方法注解要配合类注解使用
在 Spring 框架的设计中 ,⽅法注解 @Bean 要配合类注解才能将对象正常的存储到Spring 容器中
如下代码所示:
@Componentpublic class BeanConfig { @Beanpublic User user(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;}}
再次执⾏以上代码 ,运⾏结果如下:

1.3定义多个对象
多数据源的场景, 类是同⼀个, 但是配置不同, 指向不同的数据源.
@Component
public class BeanConfig {@Beanpublic User user1(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;}@Beanpublic User user2(){User user = new User();user.setName("lisi");user.setAge(28);return user;}}
获取对象:
@SpringBootApplication
public class TestSpringTwoApplication {public static void main(String[] args) {ApplicationContext context = SpringApplication.run(TestSpringTwoApplication.class, args);//从Spring上下⽂中获取对象User user1 = (User) context.getBean("user1");User user2 = (User) context.getBean("user2");//使⽤对象System.out.println(user1);System.out.println(user2);}
}
运行结果:

1.4重命名Bean
可以通过设置 name 属性给 Bean 对象进⾏重命名操作 ,如下代码所示:
@Bean(name = {"u1","user1"})public User user1(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;}
此时我们使用u1就可以获取到User对象:
User u1 = (User) context.getBean("u1");
name={} 可以省略 ,如下代码所⽰:
@Bean({"u1","user1"})public User user1(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;}
只有⼀个名称时, {}也可以省略, 如:
@Bean("u1")public User user1(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;}
1.5扫描路径
使⽤前⾯学习的四个注解声明的bean想要⽣效 ,还需要被Spring扫描
通过修改项目工程的目录结构进行测试:

运行结果:

解释: 没有bean的名称为u1,
使⽤五⼤注解声明的bean ,要想⽣效, 还需要配置扫描路径, 让Spring扫描到这些注解也就是通过
@ComponentScan来配置扫描路径.
@ComponentScan({"com.example.demo"})
@SpringBootApplication
public class TestSpringTwoApplication {public static void main(String[] args) {ApplicationContext context = SpringApplication.run(TestSpringTwoApplication.class,args);//从Spring上下⽂中获取对象User user =context.getBean(User.class);//使⽤对象System.out.println(user);}
}
@ComponentScan注解虽然没有显式配置,但是实际已经包含在了启动类声明注解
@SpringBootApplication中了,默认扫描的范围是启动类所在包及其子包

2.DI详解
2.1DI与IoC的关系
DI(Dependency Injection,依赖注入)和 IoC(Inversion of Control,控制反转)有着密切的关系。 可以说 DI 是实现 IoC 的一种具体方式。 IoC 是一种设计思想,强调将对象之间的控制权进行反转,不再由对象自己去创建或获取其依赖,而是由外部(如框架)来控制和管理依赖关系的创建和注入。 而 DI 则侧重于具体的将依赖对象注入到目标对象的操作,它是实现 IoC 理念的重要手段之一。通过 DI,依赖对象在合适的时候被准确地注入到需要它们的对象中,从而体现了 IoC 的原则。 简单来说,IoC 是更宏观的概念,DI 是实现 IoC 的具体策略和机制。
关于依赖注⼊, Spring也给我们提供了三种⽅式:
属性注⼊(Field Injection)、构造⽅法注⼊(Constructor Injection)、Setter 注⼊(Setter Injection)
2.2属性注入
@SpringBootApplicationpublic class SpringIocDemoApplication { public static void main(String[] args) { //获取Spring上下⽂对象ApplicationContext context = SpringApplication.run(SpringIocDemoApplicatio //从Spring上下⽂中获取对象UserController userController = (UserController) context.getBean("userCont //使⽤对象userController.sayHi(); 11 }}
属性注⼊是使用@Autowired实现的 ,将 Service 类注⼊到 Controller 类中.
Service类的实现代码如下:
import org.springframework.stereotype.Service; @Servicepublic class UserService {public void sayHi() {System.out.println("Hi,UserService");}}
Controller 类的实现代码如下:
@Controllerpublic class UserController { //注⼊⽅法1: 属性注⼊@Autowiredprivate UserService userService;public void sayHi(){System.out.println("hi,UserController...");userService.sayHi();}}
获取Controller中的sayHi方法:
@SpringBootApplicationpublic class SpringIocDemoApplication { public static void main(String[] args) { //获取Spring上下⽂对象ApplicationContext context = SpringApplication.run(TestSpringTwoApplication.class,args);//从Spring上下⽂中获取对象UserController userController = context.getBean(UserController.class);//使⽤对象userController.sayHi(); }}
运行结果为:

2.3构造方法注入
构造方法注入是在类的构造方法中实现注入,如下代码所示:
@Controller
public class UserController2 { //注⼊⽅法2: 构造⽅法private UserService userService; @Autowiredpublic UserController2(UserService userService) {this.userService = userService;} public void sayHi(){System.out.println("hi,UserController2...");userService.sayHi();}}
注意事项:如果类只有⼀个构造⽅法 ,那么@Autowired 注解可以省略;如果类中有多个构造⽅法, 那么需要添加上@Autowired 来明确指定到底使⽤哪个构造⽅法。
2.4Setter注入
Setter 注⼊和属性的 Setter 方法实现类似 ,只不过在设置 set 方法的时候需要加上@Autowired 注解 ,如下代码所示:
@Controllerpublic class UserController3 { //注⼊⽅法3: Setter⽅法注⼊private UserService userService; @Autowiredpublic void setUserService(UserService userService) {this.userService = userService;} public void sayHi(){System.out.println("hi,UserController3...");userService.sayHi();}}
2.5 三种注入优缺点分析
属性注⼊
优点: 简洁 ,使⽤⽅便;
缺点:只能⽤于 IoC 容器 ,并且只有在使⽤的时候才会出现 NPE( 空指针异常)、 不能注入⼀个Final修饰的属性
构造函数注⼊(Spring 4.X推荐)
优点:可以注⼊final修饰的属性、注⼊的对象不会被修改、依赖对象在使⽤前⼀定会被完全初始化 ,因为依赖是在类的构造⽅法中执⾏的 ,⽽构造⽅法是在类加载阶段就会执⾏的⽅法、 通⽤性好, 构造⽅法是JDK⽀持的, 所以更换任何框架,他都是适⽤的
缺点: 注入多个对象时, 代码会比较繁琐
Setter注⼊(Spring 3.X推荐)
优点: ⽅便在类实例之后, 重新对该对象进⾏配置或者注⼊
缺点:不能注⼊⼀个Final修饰的属性、注⼊对象可能会被改变, 因为setter⽅法可能会被多次调⽤ , 就有被修改的风险.
2.6Autowired存在问题
当同⼀类型存在多个bean时, 使⽤@Autowired会存在问题
@Componentpublic class BeanConfig { @Bean("u1")public User user1(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;} @Beanpublic User user2() {User user = new User();user.setName("lisi");user.setAge(19);return user;}}
@Controllerpublic class UserController { //注⼊user @Autowiredprivate User user;public void sayHi(){System.out.println("hi,UserController...");userService.sayHi();System.out.println(user);}}
运行结果:
报错的原因是 ,⾮唯—的 Bean 对象。
Spring提供了以下几种解决⽅案:
2.6.1Primary
@Primary注解: 当存在多个相同类型的Bean注⼊时 ,加上@Primary注解 ,来确定默认的实现.
@Componentpublic class BeanConfig { @Primary //指定该bean为默认bean的实现@Bean("u1")public User user1(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;} @Beanpublic User user2() {User user = new User();user.setName("lisi");user.setAge(19);return user;}}
2.6.2Qualifier
指定当前要注⼊的bean对象。 在@Qualifier的value属性中 ,指定注⼊的bean 的名称。
@Qualifier注解不能单独使⽤ ,必须配合@Autowired使用
@Controllerpublic class UserController {@Qualifier("user2") //指定bean名称@Autowiredprivate User user;public void sayHi(){System.out.println("hi,UserController...");System.out.println(user);}}
2.6.3Resource
使⽤@Resource注解:是按照bean的名称进⾏注⼊。通过name属性指定要注⼊的bean的名称。
@Controllerpublic class UserController { @Resource(name = "user2")private User user; public void sayHi(){System.out.println("hi,UserController...");System.out.println(user);}}
@Autowird 与 @Resource的区别
• @Autowired 是spring框架提供的注解 ,而@Resource是JDK提供的注解
• @Autowired 默认是按照类型注⼊ ,⽽@Resource是按照名称注⼊ . 相⽐于 @Autowired 来说, @Resource ⽀持更多的参数设置 ,例如 name 设置 ,根据名称获取 Bean。
相关文章:
详解Spring IoCDI(二)
目录 承接上文:详解Spring IoC&DI (一) 1.IoC详解 1.1方法注解Bean 1.2方法注解要配合类注解使用 1.3定义多个对象 1.4重命名Bean 1.5扫描路径 2.DI详解 2.1DI与IoC的关系 2.2属性注入 2.3构造方法注入 2.4Setter注入 2.5 三…...
说明白计算机网络之TCP的流量控制与拥塞控制之慢开始算法与拥塞避免算法
TCP的流量控制 利用滑动窗口实现流量控制 设A向B发送数据,连接建立时候,B告诉A自身的接收窗口大小,A的发送窗口大小不能超过接收方B的窗口大小 流量控制:发送方发送速率不要太快,要让接收方来得及接收。窗口大小的单…...
这款信创FTP软件,可实现安全稳定的文件传输
信创,即信息技术应用创新,2018年以来,受“华为、中兴事件”影响,国家将信创产业纳入国家战略,并提出了“28n”发展体系。“8”具体指金融、石油、电力、电信、交通、航空航天、医院、教育等主要行业。目前企业使用比较…...
代码随想录算法训练营第十天|232.用栈实现队列、225. 用队列实现栈
232.用栈实现队列 题目链接:232. 用栈实现队列 文档讲解:代码随想录 状态:写出来 ,但差强人意 思路: 定义两个容器,可以是Stack,也可以是Deque,stackIn相当于临时容器,用来存放元素&…...
STM32 IIC协议
本文代码使用 HAL 库。 文章目录 前言一、什么是IIC协议二、IIC信号三、IIC协议的通讯时序1. 写操作2. 读操作 四、上拉电阻作用总结 前言 从这篇文章开始为大家介绍一些通信协议,包括 UART,SPI,IIC等。 UART串口通讯协议 SPI通信协议 一、…...
Java生成随机数的几种方式
随机数,在一些特殊场景下,是非常常用的。比如一些测试和验证场景、安全加密、随机抽样等都有随机数的‘身影’。 一、 使用java.util.Random类 java.util.Random类提供了更全面的随机数生成功能,包括随机整数、随机浮点数、随机布尔值等。 p…...
【面试】什么是Java虚拟机
目录 1. 说明2. 关键点 1. 说明 1.Java虚拟机(Java Virtual Machine,简称JVM)是运行所有Java程序的抽象计算机,是Java语言的运行环境。2.JVM是Java平台无关性的关键,它允许Java程序在任何支持JVM的硬件和操作系统上运…...
Go 语言的基本构成、要素与编写规范
Go 语言,作为由 Google 开发的现代编程语言,以其简洁、高效和并发编程能力而著称。在构建高性能分布式系统和现代软件开发中,Go 语言正日益受到欢迎。本篇文章将详细探讨 Go 语言程序结构的各个要素,包括函数定义、注释规范、数据…...
从了解到掌握 Spark 计算框架(二)RDD
文章目录 RDD 概述RDD 组成RDD 的作用RDD 算子分类RDD 的创建1.从外部数据源读取2.从已有的集合或数组创建3.从已有的 RDD 进行转换 RDD 常用算子大全转换算子行动算子 RDD 算子综合练习RDD 依赖关系窄依赖宽依赖宽窄依赖算子区分 RDD 血统信息血统信息的作用血统信息的组成代码…...
香橙派OrangePi AIpro上手笔记——之USB摄像头目标检测方案测试(三)
整期笔记索引 香橙派OrangePi AIpro上手笔记——之USB摄像头目标检测方案测试(一) 香橙派OrangePi AIpro上手笔记——之USB摄像头目标检测方案测试(二) 香橙派OrangePi AIpro上手笔记——之USB摄像头目标检测方案测试(…...
【git】常用命令
删除 删除本地分支: // 删除本地分支 git branch -d localBranchName 删除远程仓库分支 git push origin --delete <branch_name> 验证远程分支是否删除 git fetch -p //会清理已经删除的远端分支的引用 git branch -r //列出所有远端分支࿰…...
JavaWeb_MySQL数据库
数据库: MySQL数据模型: MySQL是关系型数据库。 SQL: 简介 分类: 数据库设计-DDL 对数据库操作: 表操作: 小练习: 创建下表 SQL代码: create table tb_user (id int primar…...
中国BI步入增长大周期,腾讯云ChatBI加速AI+BI融合
过去十年,大数据技术的快速发展,让数据消费前进一大步,数据价值得到一定程度的挖掘与释放,真正开启了“用数”的大时代。但数据分析繁杂的技术栈、复杂的处理过程以及程式化的交互方式,让“数据消费”的门槛始终降不下…...
揭秘Python:下划线的特殊用法,你绝对想不到!
在Python编程中,下划线(underscore)是一个常见而又强大的工具。它不仅仅是一个普通的字符,而是具有特殊含义和用法的符号。今天,我们就来揭开Python下划线的神秘面纱,探索它的各种妙用。 下划线的基本用法…...
深入探索Java世界中的Jackson魔法:玩转JsonNode
哈喽,大家好,我是木头左! 揭秘Jackson库:JSON处理的瑞士军刀 在Java的世界里,处理JSON数据就像是一场探险。幸运的是,Jackson库就像一把多功能的瑞士军刀,为提供了强大而灵活的工具来解析和操作…...
为什么要使用动态代理IP?
一、什么是动态代理IP? 动态代理IP是指利用代理服务器来转发网络请求,并通过不断更新IP地址来保护访问者的原始IP,从而达到匿名访问、保护隐私和提高访问安全性的目的。动态代理IP在多个领域中都有广泛的应用,能够帮助用户…...
【PB案例学习笔记】-09滚动条使用
写在前面 这是PB案例学习笔记系列文章的第8篇,该系列文章适合具有一定PB基础的读者。 通过一个个由浅入深的编程实战案例学习,提高编程技巧,以保证小伙伴们能应付公司的各种开发需求。 文章中设计到的源码,小凡都上传到了gitee…...
C++中常见的构造函数类别
目录 摘要 默认构造函数(Default Constructor): 带参数的构造函数(Parameterized Constructor): 拷贝构造函数(Copy Constructor): 移动构造函数(Move C…...
万界星空科技MES系统功能介绍
制造执行系统或MES 是一个全面的动态软件系统,用于监视、跟踪、记录和控制从原材料到成品的制造过程。MES在企业资源规划(ERP) 和过程控制系统之间提供了一个功能层,为决策者提供了提高车间效率和优化生产所需的数据。 万界星空科技MES 系统基础功能&am…...
炸裂的开源AI语音生成模型ChatTTS
今天看到GitHub上开源了一个非常厉害的AI语音生成模型ChatTTS,可以生成和人类声音非常接近的语音,而且有语气、语调、可以停顿和发出笑声,再也没有了以前的AI味道 体验地址:https://colab.research.google.com/drive/1MYep5f0-BJ…...
《Playwright:微软的自动化测试工具详解》
Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...
Typeerror: cannot read properties of undefined (reading ‘XXX‘)
最近需要在离线机器上运行软件,所以得把软件用docker打包起来,大部分功能都没问题,出了一个奇怪的事情。同样的代码,在本机上用vscode可以运行起来,但是打包之后在docker里出现了问题。使用的是dialog组件,…...
技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...
[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.
ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #:…...
关于easyexcel动态下拉选问题处理
前些日子突然碰到一个问题,说是客户的导入文件模版想支持部分导入内容的下拉选,于是我就找了easyexcel官网寻找解决方案,并没有找到合适的方案,没办法只能自己动手并分享出来,针对Java生成Excel下拉菜单时因选项过多导…...
nnUNet V2修改网络——暴力替换网络为UNet++
更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…...
实战设计模式之模板方法模式
概述 模板方法模式定义了一个操作中的算法骨架,并将某些步骤延迟到子类中实现。模板方法使得子类可以在不改变算法结构的前提下,重新定义算法中的某些步骤。简单来说,就是在一个方法中定义了要执行的步骤顺序或算法框架,但允许子类…...
echarts使用graphic强行给图增加一个边框(边框根据自己的图形大小设置)- 适用于无法使用dom的样式
pdf-lib https://blog.csdn.net/Shi_haoliu/article/details/148157624?spm1001.2014.3001.5501 为了完成在pdf中导出echarts图,如果边框加在dom上面,pdf-lib导出svg的时候并不会导出边框,所以只能在echarts图上面加边框 grid的边框是在图里…...
