四、Spring初识IoC和DI

devtools/2025/1/23 16:37:09/

一、初识IoC和DI

1.1Spring是什么?

我们知道了Spring是⼀个开源框架,他让我们的开发更加简单.他⽀持⼴泛的应⽤场 景,有着活跃⽽庞⼤的社区,这也是Spring能够⻓久不衰的原因. 但是这个概念相对来说,还是⽐较抽象. 我们⽤⼀句更具体的话来概括Spring,那就是:Spring是包含了众多⼯具⽅法的IoC容器

1.1.1 容器

容器是⽤来容纳某种物品的(基本)装置。⸺来⾃:百度百科 ⽣活中的⽔杯,垃圾桶,冰箱等等这些都是容器.

在比如:

List/Map->数据存储容器
Tomcat->Web容器

1.1.2 IoC是什么

在类上⾯添加 @RestController 和 @Controller 注解,就是把这个对象交给Spring管理,Spring框架启动时就会加载该类.把对象交 给Spring管理,就是IoC思想

IoC: Inversion of Control (控制反转),也就是说Spring是⼀个"控制反转"的容器

控制反转是什么?----->  当需要某个对象时,传统开发模式中需要⾃⼰通过new创建对象,现在不需要再进⾏创建, 把创建对象的任务交给容器, 程序中只需要依赖注⼊(DependencyInjection,DI)就可以了. 这个容器称为:IoC容器. Spring是⼀个IoC容器,所以有时Spring也称为Spring容器. 

举个生活中的例子:

想象你每天早上都需要一杯咖啡。通常情况下,你自己去厨房找咖啡机和咖啡豆来做咖啡。但在控制反转的情况下,你的家人已经知道你喜欢喝咖啡,并且在你起床前就把泡好的咖啡放在桌上等你。这里,你不再需要自己去找资源(咖啡机和咖啡豆),而是这些资源被“注入”给了你。这就像是依赖注入,外部环境(你的家人)负责准备并提供你需要的东西这种方式让早晨的流程变得更简单、直接,也更灵活,因为你不需要关心咖啡的准备工作了。这就是控制反转的基本思想:将对象的创建和管理从对象自身转移到外部环境。

1.2 IoC的介绍

1.2.1 传统的程序开发

需求:造一辆车

先设计轮⼦(Tire),然后根据轮⼦的⼤⼩设计底盘(Bottom),接着根据底盘设计⻋⾝(Framework),最 后根据⻋⾝设计好整个汽⻋(Car)。这⾥就出现了⼀个"依赖"关系:汽⻋依赖⻋⾝,⻋⾝依赖底盘,底 盘依赖轮⼦.

代码实现:

java">import org.w3c.dom.ls.LSOutput;//TIP To <b>Run</b> code, press <shortcut actionId="Run"/> or
// click the <icon src="AllIcons.Actions.Execute"/> icon in the gutter.
public class Main {public static void main(String[] args) {Car car = new Car();}
}//汽车类
class Car {private Tramework tramework;public Car() {tramework = new Tramework();System.out.println("Car init...");}
}//车身类
class Tramework {private Bottom bottom;public Tramework() {bottom = new Bottom();System.out.println("Tramework init...");}
}//地盘类
class Bottom {private Tire tire;public Bottom() {tire = new Tire();System.out.println("Bottom init...");}
}//轮胎类
class Tire {private int size;public Tire() {this.size = 17;System.out.println("Tire size : " + this.size);}
}

当我们要去添加轮胎类的Tire构造方法的形参编译时会出现一层一层的关联报错!

通过上述案例会发现这样的设计 代码可维护型很低,程序的耦合度⾮常⾼(修改⼀处代码,影响其他处的代码修改).

1.2.2 解决方案

尝试换⼀种思路,我们先设计汽⻋的⼤概样⼦,然后根据汽⻋的样⼦来设计⻋⾝,根据⻋⾝来设计 底盘,最后根据底盘来设计轮⼦.这时候,依赖关系就倒置过来了:轮⼦依赖底盘,底盘依赖⻋⾝, ⻋⾝依赖汽⻋。

我们可以尝试不在每个类中⾃⼰创建下级类,如果⾃⼰创建下级类就会出现当下级类发⽣改变操作, ⾃⼰也要跟着修改. 此时,我们只需要将原来由⾃⼰创建的下级类,改为传递的⽅式(也就是注⼊的⽅式),因为我们不 需要在当前类中创建下级类了,所以下级类即使发⽣变化(创建或减少参数),当前类本⾝也⽆需修 改任何代码,这样就完成了程序的解耦. 

java">public class Main {public static void main(String[] args) {Tire tire = new Tire(17);Bottom bottom = new Bottom(tire);Framework framework = new Framework(bottom);Car car = new Car(framework);}
}//汽车类
class Car {private Framework tramework;public Car(Framework framework) {this.tramework = framework;System.out.println("Car init...");}
}//车身类
class Framework {private Bottom bottom;public Framework(Bottom bottom) {this.bottom = bottom;System.out.println("Tramework init...");}
}//地盘类
class Bottom {private Tire tire;public Bottom(Tire tire) {this.tire = tire;System.out.println("Bottom init...");}
}//轮胎类
class Tire {private int size;public Tire(int size) {this.size = size;System.out.println("Tire size : " + this.size);}
}

代码经过以上调整,⽆论底层类如何变化,整个调⽤链是不⽤做任何改变的,这样就完成了代码之间 的解耦,从⽽实现了更加灵活、通⽤的程序设计了。

1.2.3 IoC的优点

在传统的代码中对象创建顺序是:Car->Framework->Bottom->Tire
改进之后解耦的代码的对象创建顺序是:Tire->Bottom->Framework->Car

我们发现了⼀个规律,通⽤程序的实现代码,类的创建顺序是反的,传统代码是Car控制并创建了 Framework,Framework创建并创建了Bottom,依次往下,⽽改进之后的控制权发⽣的反转,不再是使⽤⽅对象创建并控制依赖对象了,⽽是把依赖对象注⼊将当前对象中,依赖对象的控制权不再由当前类控制了. 这样的话,即使依赖类发⽣任何改变,当前类都是不受影响的,这就是典型的控制反转,也就是IoC的 实现思想。

从上⾯也可以看出来,IoC容器具备以下优点:

1、资源不由使⽤资源的双⽅管理,⽽由不使⽤资源的第三⽅管理,这可以带来很多好处。第⼀,资源集 中管理,实现资源的可配置和易管理。

2、降低了使⽤资源双⽅的依赖程度,也就是我们说的耦合度。

3、资源集中管理: IoC容器会帮我们管理⼀些资源(对象等),我们需要使⽤时,只需要从IoC容器中            去取就可以了。

4、我们在创建实例的时候不需要了解其中的细节,降低了使⽤资源双⽅的依赖程度,也就是耦合            度。

1.3 DI 介绍

DI: DependencyInjection(依赖注⼊) 容器在运⾏期间,动态的为应⽤程序提供运⾏时所依赖的资源,称之为依赖注⼊

依赖注⼊(DI)和控制反转(IoC)是从不同的⻆度的描述的同⼀件事情,依赖注⼊是从应⽤程序的⻆度来描述,就是指通过引⼊IoC容器,利⽤依赖关系注⼊的⽅式,实现对象之间的解耦.

上述代码中,是通过构造函数的⽅式,把依赖对象注⼊到需要使⽤的对象中的

 IoC 是⼀种思想,也是"⽬标",⽽思想只是⼀种指导原则,最终还是要有可⾏的落地⽅案,⽽DI就属于 具体的实现。所以也可以说,DI是IoC的⼀种实现.

⽐如说我今天⼼情⽐较好,吃⼀顿好的犒劳犒劳⾃⼰,那么"吃⼀顿好的"是思想和⽬标(是 IoC),但最后我是吃海底捞还是杨国福?这就是具体的实现,就是DI。

二. IoC &DI使用

既然Spring是⼀个IoC(控制反转)容器,作为容器,那么它就具备两个最基础的功能:

• 存

• 取

Spring 容器管理的主要是对象,这些对象,我们称之为"Bean".我们把这些对象交由Spring管理,由 Spring来负责对象的创建和销毁.我们程序只需要告诉Spring,哪些需要存,以及如何从Spring中取出 对象

⽬标:把BookDao,BookService交给Spring管理,完成Controller层,Service层,Dao层的解耦

步骤:

1. Service层及Dao层的实现类,交给Spring管理: 使⽤注解: @Component

2. 在Controller层和Service层注⼊运⾏时依赖的对象:使⽤注解 @Autowired

实现:

1. 把BookDao交给Spring管理,由Spring来管理对象

java">package com.example.book.dao;import com.example.book.model.BookInfo;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;@Component
public class BookDao {public List<BookInfo> mockData() {//对于已知的数据量 建议初始化容量List<BookInfo> bookInfos = new ArrayList<>(15);for (int i = 1; i <= 15; i++) {BookInfo bookInfo = new BookInfo();bookInfo.setId(1);bookInfo.setBookName("图书" + i);bookInfo.setAuthor("作者" + i);bookInfo.setCount(new Random().nextInt(200));bookInfo.setPrice(new BigDecimal(new Random().nextInt(100)));bookInfo.setPublish("出版社" + i);bookInfo.setStatus(i % 5 == 0 ? 0 : 1);bookInfos.add(bookInfo);}return bookInfos;}
}

2.把BookService交给Spring管理,由Spring来管理对象

java">package com.example.book.service;import com.example.book.dao.BookDao;
import com.example.book.model.BookInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import java.util.List;@Component
public class BookService {@Autowiredprivate BookDao bookDao;public List<BookInfo> getBookList() {//1、获取图书数据//2、对图书的数据进行处理//3、返回数据//mock 表示虚拟假数据List<BookInfo> bookInfos =bookDao.mockData();for (BookInfo bookInfo : bookInfos) {if (bookInfo.getStatus() == 1) {bookInfo.setStatusCN("可借阅");} else {bookInfo.setStatusCN("不可借阅");}}return bookInfos;}
}

3.删除创建BookDao的代码,从Spring中获取对象

java">package com.example.book.service;import com.example.book.dao.BookDao;
import com.example.book.model.BookInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import java.util.List;@Component
public class BookService {@Autowiredprivate BookDao bookDao;public List<BookInfo> getBookList() {//1、获取图书数据//2、对图书的数据进行处理//3、返回数据//mock 表示虚拟假数据List<BookInfo> bookInfos =bookDao.mockData();for (BookInfo bookInfo : bookInfos) {if (bookInfo.getStatus() == 1) {bookInfo.setStatusCN("可借阅");} else {bookInfo.setStatusCN("不可借阅");}}return bookInfos;}
}

4. 删除创建BookService的代码,从Spring中获取对象

java">package com.example.book.controller;import com.example.book.model.BookInfo;
import com.example.book.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.List;@RestController
@RequestMapping("/book")
public class BookController {@AutowiredBookService bookService ;@RequestMapping("/getBookList")public List<BookInfo> getBookList() {return bookService.getBookList();}
}


http://www.ppmy.cn/devtools/152439.html

相关文章

【QT】: 初识 QWidget 控件 | QWidget 核心属性(API) | qrc 文件

&#x1f525; 目录 1. 控件概述 控件体系的发展阶段 2. QWidget 核心属性 2.1 核心属性概览2.2 用件可用&#xff08;Enabled&#xff09; 2.3 坐标系&#xff08;Geometry&#xff09; **实例 1: 控制按钮的位置**实例 2: 表白 程序 2.4 窗口标题&#xff08;windowTiltle&a…

电梯系统的UML文档06

系统传感器 系统值是用于控制系统的。在类图中系统传感器用一个箭头和系统控制对象连接。 类图中的系统传感器包括AtFloor、电梯呼叫器、关门、开门、门反转、楼层呼叫器和驱动&#xff08;AtFloor&#xff0c;CarCall&#xff0c;DoorClosed&#xff0c;DoorOpen&#xff0c;…

Python 模拟真人鼠标轨迹算法 - 防止游戏检测

一.简介 鼠标轨迹算法是一种模拟人类鼠标操作的程序&#xff0c;它能够模拟出自然而真实的鼠标移动路径。 鼠标轨迹算法的底层实现采用C/C语言&#xff0c;原因在于C/C提供了高性能的执行能力和直接访问操作系统底层资源的能力。 鼠标轨迹算法具有以下优势&#xff1a; 模拟…

npm操作大全:从入门到精通

引言 在现代前端开发中&#xff0c;npm&#xff08;Node Package Manager&#xff09;是不可或缺的工具。无论是安装依赖、管理项目&#xff0c;还是发布自己的包&#xff0c;npm都扮演着重要的角色。本文将带你从npm的基础操作开始&#xff0c;逐步深入到高级用法&#xff0c…

从CentOS到龙蜥:企业级Linux迁移实践记录(容器与应用)

引言&#xff1a; 在企业级Linux环境中&#xff0c;容器技术已经成为应用部署和管理的核心工具。随着技术的不断演进&#xff0c;企业用户对容器化工具的需求也在逐步升级。在本系列的前几篇文章中&#xff0c;我们探讨了龙蜥操作系统&#xff08;OpenAnolis&#xff09;的安装…

高级java每日一道面试题-2025年01月19日-框架篇[Mybatis篇]-MyBatis 中见过什么设计模式 ?

如果有遗漏,评论区告诉我进行补充 面试官: MyBatis 中见过什么设计模式 ? 我回答: 1. 工厂模式&#xff08;Factory Pattern&#xff09; 定义&#xff1a;工厂模式是一种创建型模式&#xff0c;它提供了一种创建对象的最佳方式&#xff0c;将对象创建过程抽象化&#xff…

mysql的mvcc

快速搞懂mvcc 全称 multi-version concurrency control 多版本并发控制。自动开启事务undo log读视图(read_view)结果过滤mvcc只在读已提交和可重复读隔离级别下运作读已提交隔离级别下&#xff0c;可重复读隔离级别下&#xff0c;总的来说mvcc是为了提高数据库并发性能而设计的…

2025美赛Latex模板可直接运行!O奖自用版

目录 01 预览图02 Latex模板main.texeasymcm.sty 2025年美国大学生数学建模大赛&#xff08;2025年1月23日&#xff09;马上开始啦&#xff0c;大家一定要提前准备好模板&#xff0c;Latex或者是Word都可以&#xff0c;这里我整理了之前比赛用到的模板&#xff0c;并进行了一些…