详解Spring IoCDI(一)
目录
1.什么是IoC
2.IoC应用场景(案例分析)
2.1传统程序开发
2.2问题分析
2.3解决方案
2.4IoC 优势
3. DI概念
4.IoC详解
4.1Bean的存储
4.2@Controller(控制器存储)
4.3获取Bean
4.4Bean相关注解
1.什么是IoC
Spring是⼀个开源框架, 他让我们的开发更加简单、Spring 是包含了众多工具⽅法的 IoC 容器 、
IoC(Inversion of Control,控制反转)是Spring的核心思想,在传统的编程模式中,对象的创建和依赖关系的管理通常由程序自身来完成。而在使用了 IoC 思想的框架(如 Spring)中,这些对象的创建以及对象之间依赖关系的建立等控制权由框架来接管,而不是由应用程序代码直接控制
所谓的IOC称之为控制反转,简单来说就是将对象的创建的权力及对象生命周期的管理过程交由Spring框架来处理,从此在开发过程中不在需要关注对象的创建和生命周期的管理,而是在需要的时候由Spring框架提供,这个由Spring框架管理对象创建和生命周期的机制称之为控制反转。
2.IoC应用场景(案例分析)
2.1传统程序开发
需求:造出一辆能跑的车
先设计轮⼦(Tire) ,然后根据轮⼦的⼤⼩设计底盘(Bottom) ,接着根据底盘设计⻋⾝(Framework) ,最后根据⻋⾝设计好整个汽⻋(Car)。
这⾥就出现了⼀个"依赖"关系:汽车依赖车身,车身依赖底盘 ,底盘依赖轮⼦ .
最终程序的实现代码如下:
public class Car {private Framework framework;public Car() {framework = new Framework();System.out.println("car init...");}public void run() {System.out.println("car run...");}
}public class Framework {private Bottom bottom;public Framework() {bottom = new Bottom();System.out.println("framework init....");}
}public class Bottom {private Tire tire;public Bottom() {tire = new Tire();System.out.println("bottom init...");}
}public class Tire {public Tire() {System.out.println("tire init...size:"+size);}
}
2.2问题分析
这样的设计看起来没问题 ,但是可维护性却很低.接下来需求变更,我们需要加工多种尺寸的轮胎.
那这个时候就要对上⾯的程序进⾏修改了 ,修改后的代码如下所示:
修改之后, 其他调⽤程序也会报错, 我们需要继续修改
从以上代码可以看出以上程序的问题是: 程序的耦合度⾮常⾼,当最底层代码改动之后 ,整个调用链上的所有代码都需要修改.
2.3解决方案
我们尝试换⼀种思路, 我们先设计汽车的⼤概样子 ,然后根据汽车的样子来设计车身,根据车身来设计 底盘 ,最后根据底盘来设计轮子 . 这时候 ,依赖关系就倒置过来了:轮⼦依赖底盘 , 底盘依赖车身,车身依赖汽车
此时 ,我们只需要将原来由⾃⼰创建的下级类 ,改为传递的⽅式(也就是注入的⽅式), 因为我们不需要在当前类中创建下级类了 ,所以下级类即使发⽣变化(创建或减少参数), 当前类本⾝也⽆需修改任何代码 ,这样就完成了程序的解耦.
public class Car {private Framework framework;public Car(Framework framework) {this.framework = framework;System.out.println("car init...");}public void run(){System.out.println("car run...");}
}
public class Framework {private Bottom bottom;public Framework(Bottom bottom) {this.bottom = bottom;System.out.println("framework init....");}
}
public class Bottom {private Tire tire;public Bottom(Tire tire) {this.tire = tire;System.out.println("bottom init....");}
}
public class Tire {private int size;public Tire(int size) {this.size = size;this.color= color;System.out.println("tire init...size:"+size);}
}
代码经过以上调整 ,⽆论底层类如何变化 ,整个调⽤链是不⽤做任何改变的 ,这样就完成了代码之间的解耦 ,从而实现了更加灵活、通⽤的程序设计了。
2.4IoC 优势
在传统的代码中对象创建顺序是:Car -> Framework -> Bottom -> Tire
改进之后解耦的代码的对象创建顺序是:Tire -> Bottom -> Framework -> Car
通⽤程序的实现代码 ,类的创建顺序是反的 ,传统代码是 Car 控制并创建了Framework ,Framework 创建并创建了 Bottom ,依次往下 ,⽽改进之后的控制权发⽣的反转 ,不是使⽤⽅对象创建并控制依赖对象了,是把依赖对象注⼊将当前对象中,依赖对象的控制权不再由当前类控制
这样的话, 即使依赖类发⽣任何改变 , 当前类都是不受影响的 ,这就是典型的控制反转 ,也就是 IoC 的实现思想。
IoC 的优点主要包括以下几点:
- 降低耦合度:使组件之间的依赖关系更加松散,便于系统的扩展和维护。
- 提高代码复用性:组件可以更方便地在不同场景中复用。
- 增强灵活性:可以更轻松地替换或修改依赖的对象,而不影响其他部分代码。
- 便于测试:可以方便地模拟和替换依赖对象,进行单元测试。
- 提升开发效率:开发者无需花费大量时间处理对象创建和依赖管理的繁琐细节。
- 更好的架构管理:有助于构建更清晰、合理的系统架构。
3. DI概念
IoC 是一种设计思想,而 DI(Dependency Injection,依赖注入)是实现 IoC 的一种重要方式。
DI 具体指的是将对象之间的依赖关系,通过一定的方式(如构造器注入、Setter 方法注入、字段注入等)在运行时动态地注入到对象中。
可以说 DI 是 IoC 思想在具体技术实现层面的体现,它们紧密相关,共同作用来实现对象创建和依赖管理的解耦与灵活配置。
创建Student类:
public class Student {private String name;public Student(String name) {this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}
}
创建一个Course类,并通过注解注入Student对象:
@Service
public class Course {@Autowiredprivate Student student;public void showDetails() {System.out.println("依赖注入学生姓名:" + student.getName());}
}
4.IoC详解
通过上⾯的案例, 我们已经知道了Spring IoC 和DI的基本操作, 接下来我们来系统的学习Spring IoC和DI 的操作.前⾯我们提到IoC控制反转 ,就是将对象的控制权交给Spring的IOC容器 , 由IOC容器创建及管理对象。也就是bean的存储.
4.1Bean的存储
要把某个对象交给IOC容器管理 ,需要在类上添加⼀个注解:@Component
而Spring框架为了更好的服务web应⽤程序, 提供了更丰富的注解.
共有两类注解类型可以实现:
类注解:@Controller、@Service、@Repository、@Component、@Configuration.
⽅法注解:@Bean.
4.2@Controller(控制器存储)
使用@Controller 存储 bean 的代码如下所示:
@Controller // 将对象存储到 Spring 中public class UserController {public void sayHi(){System.out.println("hi,UserController...");}}
如何观察这个对象已经存在Spring容器当中了呢? 接下来我们学习如何从Spring容器中获取对象
@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.sayHello();}
}
}
观察运⾏结果, 发现成功从Spring中获取到Controller对象, 并执⾏Controller的sayHello⽅法
如果把@Controller删掉, 再观察运⾏结果
报错信息显⽰: 找不到类型是: com.example.demo.controller.UserController的bean
获取bean对象的其他⽅式:
上述代码是根据类型来查找对象, 如果Spring容器中, 同⼀个类型存在多个bean的话, 怎么获取呢
ApplicationContext 也提供了其他获取bean的⽅式, ApplicationContext 获取bean对象的功能, 是父类BeanFactory提供的功能.
// 1. 根据bean名称获取beanObject getBean(String var1) throws BeansException;// 2. 根据bean名称和类型获取bean<T> T getBean(String var1, Class<T> var2) throws BeansException;// 3. 按bean名称和构造函数参数动态创建bean,只适⽤于具有原型(prototype)作⽤域的beanObject getBean(String var1, Object... var2) throws BeansException;// 4. 根据类型获取bean<T> T getBean(Class<T> var1) throws BeansException;// 5. 按bean类型和构造函数参数动态创建bean,只适⽤于具有原型(prototype)作⽤域的bea<T> T getBean(Class<T> var1, Object... var2) throws BeansException;
常⽤的是上述1,2,4种, 这三种⽅式,获取到的bean是⼀样的,其中1,2种都涉及到根据名称来获取对象. bean的名称是什么呢?
Spring bean是Spring框架在运⾏时管理的对象, Spring会给管理的对象起⼀个名字. ⽐如学校管理学⽣ , 会给每个学⽣分配⼀个学号, 根据学号, 就可以找到对应的学⽣ .
Spring也是如此, 给每个对象起⼀个名字, 根据Bean的名称(BeanId)就可以获取到对应的对象.
4.3获取Bean
@SpringBootApplicationpublic class SpringIocDemoApplication { public static void main(String[] args) { //获取Spring上下⽂对象ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class,args); //从Spring上下⽂中获取对象//根据bean类型, 从Spring上下⽂中获取对象UserController userController1 = context.getBean(UserController.class); //根据bean名称, 从Spring上下⽂中获取对象UserController userController2 = (UserController) context.getBean("userController"); //根据bean类型+名称, 从Spring上下⽂中获取对象UserController userController3 = context.getBean("userController",UserController.class);System.out.println(userController1);System.out.println(userController2);System.out.println(userController3);
运⾏结果:
地址⼀样, 说明是同一个对象
继承关系和功能⽅⾯来说:
Spring 容器有两个顶级的接⼝: BeanFactory 和ApplicationContext。
其中 BeanFactory 提供了基础的访问容器的能力,
ApplicationContext 属于 BeanFactory 的⼦类 ,它除了继承了 BeanFactory 的所有功能之外, 它还拥有独特的特性 ,还添加了对国际化⽀持、资源访问⽀持、 以及事件传播等⽅⾯的⽀持
从性能⽅⾯来说:ApplicationContext 是⼀次性加载并初始化所有的 Bean 对象 ,⽽ BeanFactory 是需要那个才去加载那个 ,因此更加轻量. (空间换时间)
4.4Bean相关注解
在 Spring 中,有一些与 Bean 相关的重要注解,比如:
@Component:这是一个通用的组件注解,用于将类标识为可被 Spring 容器管理的 Bean。
@Service:通常用于标识服务层的 Bean,业务逻辑层, 处理具体的业务逻辑.
@Repository:一般用于标识数据访问层(如数据库操作相关)的 Bean。
@Controller:控制层, 接收请求, 对请求进⾏处理, 并进⾏响应.
@Configuration :配置层. 处理项⽬中的⼀些配置信息.
此外,还有@AutoWired用于自动注入依赖等注解,它们共同协作来实现对 Bean 的管理和配置
程序员看到类注解之后 ,就能直接了解当前类的用途.
相关文章:

详解Spring IoCDI(一)
目录 1.什么是IoC 2.IoC应用场景(案例分析) 2.1传统程序开发 2.2问题分析 2.3解决方案 2.4IoC 优势 3. DI概念 4.IoC详解 4.1Bean的存储 4.2Controller(控制器存储) 4.3获取Bean 4.4Bean相关注解 1.什么是IoC Spring…...

Android 14 - 绘制体系 - 概览
从Android 12开始,Android的绘制系统有结构性变化, 在绘制的生产消费者模式中,新增BLASTBufferQueue,客户端进程自行进行queue的生产和消费,随后通过Transation提交到SurfaceFlinger,如此可以使得各进程将缓…...

【RAG论文】文档树:如何提升长上下文、非连续文档、跨文档主题时的检索效果
RAPTOR Recursive Abstractive Processing for Tree-Organized RetrievalICLR 2024 Stanfordhttps://arxiv.org/pdf/2401.18059 RAPTOR(Recursive Abstractive Processing for Tree-Organized Retrieval)是一种创建新的检索增强型语言模型,它…...
【前端每日基础】day27——小程序开发
小程序开发详细介绍 基本概念 小程序:小程序是一种无需下载安装即可使用的应用。用户通过微信搜索或扫描二维码即可打开小程序。小程序具有触手可及、用完即走、体验良好的特点。 组成部分: WXML:用于描述页面的结构。 WXSS:用于…...
【C语言】指针速览
指针速览 指针1.野指针与空指针2. 空类型指针 void *3. 指针常量4. 常量指针5. 指向常量的指针常量6. 指针操作数组6.1 数组名作为函数参数 7. 多级指针8. 函数指针8.1 函数指针数组 最后 指针 指针就是内存的字节单元编号地址,指针变量就是存放地址的变量。 1.野…...
Java基础学习:深入解析Java中的位运算符
在Java中,位运算符用于对整数类型的值进行位运算。以下是Java中的位运算符: 位与(&):两位都为1时,结果为1,否则为0。 位或(|):两位中有1个为1,结果为1。 位非(~):位的反&#…...

9.Redis之list类型
list相当于链表、数据表 1.list类型基本介绍 列表中的元素是有序的"有序"的含义,要根据上下文区分~~有的时候,谈到有序,指的是"升序","降序”有的时候,谈到的有序,指的是, 顺序很关键~~如果把元素位置颠倒,顺序调换.此时得到的新的 List 和之前的 Li…...

Git 的安装和使用
一、Git 的下载和安装 目录 一、Git 的下载和安装 1. git 的下载 2. 安装 二、Git 的基本使用-操作本地仓库 1 初始化仓库 1)创建一个空目录 2)git init 2 把文件添加到版本库 1)创建文件 2)git add . 3)g…...

大模型时代的具身智能系列专题(五)
stanford宋舒然团队 宋舒然是斯坦福大学的助理教授。在此之前,他曾是哥伦比亚大学的助理教授,是Columbia Artificial Intelligence and Robotics Lab的负责人。他的研究聚焦于计算机视觉和机器人技术。本科毕业于香港科技大学。 主题相关作品 diffusio…...

基于springboot+vue的社区医院管理服务系统
开发语言:Java框架:springbootJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包:…...

车载电子电器架构 —— 智能座舱标准化意义
车载电子电器架构 —— 智能座舱标准化意义 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消…...
Compose在xml中使用滑动冲突处理
一、背景 在现有Android项目中使用Compose可能存在滑动冲突问题,例如 SmartRefreshLayoutCoordinatorLayoutComposeView(ComposeView这里又是一个LazyColumn) 二、解决方案 官方介绍:https://developer.android.google.cn/develop/ui/compose/touch-inp…...

微信网页版登录插件v1.1.1
说到如今的微信客户端,大家肯定会有很多提不完的意见或者建议。比如这几年体积越来越大,如果使用频率比较高,那占用空间就更离谱了。系统迷见过很多人电脑C盘空间爆满,都是由于微信PC版造成的。 而且,它还加了很多乱七…...

华为实训课笔记 2024
华为实训 5/205/215/225/235/275/28 5/20 5/21 5/22 5/23 5/27 5/28...

HTML静态网页成品作业(HTML+CSS)——宠物狗介绍网页(3个页面)
🎉不定期分享源码,关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 🏷️本套采用HTMLCSS,未使用Javacsript代码,共有3个页面。 二、作品演示 三、代…...

网络模型-路由策略
一、路由策略 路由策略(Routing Policy)作用于路由,主要实现了路由过滤和路由属性设置等功能,它通过改变路由属性(包括可达性)来改变网络流量所经过的路径。目的:设备在发布、接收和引入路由信息时,根据实际组网需要实施一些策略,…...
【MySQL精通之路】InnoDB(7)-锁和事务模型
1.InnoDB锁 【MySQL精通之路】InnoDB(7)-锁和事务模型(1)-锁-CSDN博客 2.InnoDB事务模型 【MySQL精通之路】InnoDB(7)-锁和事务模型(2)-事务模型-CSDN博客 3.InnoDB中不同SQL语句设置的锁 4.幻影行 5.InnoDB中的死锁 5.1InnoDB死锁示例 5.2死锁检测 …...

深度学习创新点不大但有效果,可以发论文吗?
深度学习中创新点比较小,但有效果,可以发论文吗?当然可以发,但如果想让编辑和审稿人眼前一亮,投中更高区位的论文,写作永远都是重要的。 那么怎样“讲故事”才能让论文更有吸引力?我总结了三点…...
【ARM Cache 系列文章 7.1 – ARMv8/v9 MMU 页表配置详细介绍 02 】
文章目录 Translation table descriptorTable descriptor format页面粒度和地址长度粒度(Granules)48位和52位地址TCR_ELx.DSVTCR_EL2.DSFEAT_LPA块描述符|页描述符紧接上篇文章【ARM Cache 系列文章 7 – ARMv8/v9 MMU 页表配置 01 】 Translation table descriptor</...

Mysql搭建主从同步,docker方式(一主一从)
服务器:两台Centos9 用Docker搭建主从 使用Docker拉取MySQL镜像 确保两台服务器都安装好了docker 安装docker请查看:Centos安装docker 1.两台服务器都先拉取mysql镜像 docker pull mysql 2.我这里是在 /opt/docker/mysql 下创建mysql的文件夹用来存…...

Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...

.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...
Objective-C常用命名规范总结
【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名(Class Name)2.协议名(Protocol Name)3.方法名(Method Name)4.属性名(Property Name)5.局部变量/实例变量(Local / Instance Variables&…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...

376. Wiggle Subsequence
376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...
多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
一、多模态商品数据接口的技术架构 (一)多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如,当用户上传一张“蓝色连衣裙”的图片时,接口可自动提取图像中的颜色(RGB值&…...

跨链模式:多链互操作架构与性能扩展方案
跨链模式:多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈:模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展(H2Cross架构): 适配层…...

MySQL 8.0 OCP 英文题库解析(十三)
Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...