详解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的文件夹用来存…...

【已解决】使用token登录机制,token获取不到,blog_list.html界面加载不出来
Bug产生 今天使用token完成用户登录信息的存储的时候被卡了大半天。 因为登录的功能写的已经很多了,所以今天就没有写一点验一点,而是在写完获取博客列表功功能,验证完它的后端后,了解完令牌的基本使用以及Jwt的基本使用方式——…...

【Linux 网络编程】网络的基础知识详解!
文章目录 1. 计算机网络背景2. 认识 "协议" 1. 计算机网络背景 网络互联: 多台计算机连接在一起, 完成数据共享; 🍎局域网(LAN----Local Area Network): 计算机数量更多了, 通过交换机和路由器连接。 🍎 广域网WAN: 将…...

Nacos 2.x 系列【12】配置加密插件
文章目录 1. 前言2. 安装插件2.1 编译2.2 客户端2.3 服务端 3. 测试 1. 前言 为保证用户敏感配置数据的安全,Nacos提供了配置加密的新特性。降低了用户使用的风险,也不需要再对配置进行单独的加密处理。 前提条件: 版本:老版本暂时不兼容&…...

Kubernetes和Docker对不同OS和CPU架构的适配关系
Docker Docker官网对操作系统和CPU架构的适配关系图 对于其他发行版本,Docker官方表示没有测试或验证在相应衍生发行版本上的安装,并建议针对例如Debian、Ubuntu等衍生发行版本上使用官方的对应版本。 Kubernetes X86-64 ARM64 Debian系 √ √ Re…...

LabVIEW机器设备的振动监测
振动监测是工业和机械维护中重要的一部分,通过检测和分析机械振动,提前发现潜在故障,确保设备的可靠运行。LabVIEW是一种强大的图形化编程环境,非常适合用于振动监测系统的开发和实施。以下从多个角度详细介绍LabVIEW在振动监测中…...

FreeRTOS学习笔记-基于stm32(7)任务状态查询与任务时间统计API函数
1、FreeRTOS任务相关API函数 函数描述uxTaskPriorityGet()查询某个任务的优先级vTaskPrioritySet()改变某个任务的任务优先级uxTaskGetSystemState()获取系统中任务状态vTaskGetInfo()获取某个任务信息xTaskGetApplicationTaskTag()获取某个任务的标签(Tag)值xTaskGetCurrentT…...

Flutter 中的 ElevatedButton 小部件:全面指南
Flutter 中的 ElevatedButton 小部件:全面指南 Flutter 提供了多种按钮小部件,每种都有其独特的用途和样式。ElevatedButton 是其中一种,它代表了具有凸起效果的按钮,通常用于 Material Design 风格的应用中。本文将为您提供一个…...

huggingface的self.state与self.control来源(TrainerState与TrainerControl)
文章目录 前言一、huggingface的trainer的self.state与self.control初始化调用二、TrainerState源码解读(self.state)1、huggingface中self.state初始化参数2、TrainerState类的Demo 三、TrainerControl源码解读(self.control)总结 前言 在 Hugging Face 中,self.s…...

30【Aseprite 作图】桌子——拆解
1 桌子只要画左上方,竖着5,斜着3个1,斜着两个2,斜着2个3,斜着一个5,斜着一个很长的 然后左右翻转 再上下翻转 在桌子腿部分,竖着三个直线,左右都是斜线;这是横着水平线不…...

C++设计模式-单例模式,反汇编
文章目录 25. 单例模式25.1. 饿汉式单例模式25.2. 懒汉式单例模式25.2.1. 解决方案125.2.2. 解决方案2 (推荐写法) 运行在VS2022,x86,Debug下。 25. 单例模式 单例即该类只能有一个实例。 应用:如在游戏开发中&#x…...