Spring概念:容器、Ioc、DI

news2025/1/13 6:16:42

目录

什么是容器?

什么是 IoC?

传统程序的开发

理解 Spring IoC

DI

总结


我们通常所说的 Spring 指的是 Spring Framework(Spring 框架),它是⼀个开源框架,有着活跃⽽庞⼤的社区,这就是它之所以能⻓久不衰的原因。Spring ⽀持⼴泛的应⽤场景,它可以让 Java 企业级的应⽤程序开发起来更简单。
⽤⼀句话概括 Spring:Spring 是包含了众多⼯具⽅法的 IoC 容器。


我们的重点先放在 IoC 容器上,理解它是一个什么东西。

那问题来了,什么是容器?什么是 IoC 容器?接下来我们⼀起来看 

什么是容器?

容器是用容纳某种物品的(基本)装置。

我们想想,之前课程我们接触的容器有哪些?
        List/Map -> 数据存储容器
        Tomcat -> Web 容器
        List / Map 是一个数据存储容器,这个很好理解。
但是 Tomcat 为什么是一个 Web 容器呢?
思考一下:
Tomcat 是用来运行 外部的项目,因此它是一个 Web 容器。
你有一个项目,想要运行。
肯定是要将项目部署到 Tomcat 的 webapps 目录底下,才可以运行。
此时,webapps 不就是一个项目的容器嘛!
而 webapps 目录,不就是 Tomcat 下面的一个子目录嘛。
那么,我们将 Tomcat 称为是一个容器,没有任何问题! 

什么是 IoC?

Spring 是⼀个 IoC 容器。

什么是 IoC?

IoC = Inversion of Control 翻译成中⽂是 “控制反转” 的意思。
也就是说 Spring 是⼀个 “控制反转” 的容器。
首先,明确一点:控制反转,是两个词 >> 控制 和 反转。
所谓的控制反转,指的是:之前程序的控制权是在自己手上,现在,我们把这个控制权交出去了。

一般情况下,我们在 A 类 中,想去调用 B 类中的方法,是怎么做的?
是不是 先要去new B 类对象,通过 对象 去调用 B类中的方法。
这时 B 的控制权,是我们手上的。
而 控制反转,就是将我们手上的权限,交由 “其他人” 来操作这个类。
这个“其他人”,就是 Spring 框架。
此时,我们想要 A 类中调用 B 的时候, 告诉 框架,我要在 A 中 调用 B 了。
至于 B 的生命周期,和我们没有任何关系。
这是控制反转。

前面说过: Spring 是一个 控制反转 的 容器。
也就是 像之前在传统开发的时候,所有需要我们自己去new东西,都不需要我们再去new 了。
因为我们把控制权 “反转给了” Spring 框架。
Spring 会帮我们管理所有的对象(Bean)

在 Spring 中,我们管 对象,叫做 Bean。

当我们想要在一个类中,调用另外一个类,就只需声明一下就可以拿到它了。
这就是一个 IoC 容器的定义.

下面,我们通过举一个例子,来加深 对 IoC 的理解。 

传统程序的开发

假如,我们现在构建⼀辆“车”的程序,我们的实现思路是这样的

public class Test {
    public static void main(String[] args) {
        Car car = new Car();
        car.init();
    }

}

public class Tire {
    private int size = 10;
    public void init(){
        System.out.println("tire="+size);
    }
}

public class Bottom {
    public void init(){
        Tire tire = new Tire();
        tire.init();
    }
}

public class Framework {
    public void init(){
         Bottom bottom = new Bottom();
        bottom.init();
    }
}

public class Car {
    public void init(){
        Framework framework = new Framework();
        framework.init();
    }
}

 

        大家可以发现:一个业务程序,它整个的调用链是非常长的,在实际开发中,这种场景是非常非常 常见的! !可以说:到了 EE 这一块,遇到的每一个业务,都会有这么长的调用链这是因为: 在 EE 中,是需要进行分层的!
1、控制层   2、服务层  3、数据持久层  。。底下是一个数据库。
        所有的接口在执行的时候,所有接口接收到请求,都优先送往控制层,控制层做完数据的正确性校验之后,才会轮到后面 层次进行处理,如果校验没通过,直接向前端返回相应的错误信息。然后呢,控制层校验数据通过之后,就会直接调用 服务层 (service) 进行服务的组装和调用,service 里面会决定 究竟需要调用几个接口来,去操作数据库。简单来说: service 是不操作数据库的! ! !然后,调用到的接口,就会去操作 接口底下 :对应的 数据持久层数据持久层,就是正儿八经的开始操作数据库了
        我们现在所看到的这个案例,就是非常常见的类型几乎所有的接口里面,都会这样去调用! ! ! !如果这样去调用的话,我们右边的这个代码又有什么问题呢?问题就在于,此时的代码是存在耦合性的,右边的代码是一环套一环的只要改动其中一个环节的代码,其他环节的代码都会受到影响! !

        此时,来看右边的代码,这种一旦改动,全部都要改的代码,维护起来,太麻烦!升级一个部分的功能,其它的 也要跟着改。比如: 随着时代推进,人们开始不满一成不变的产品。此时,产品经理,整辆车的构造应该根据用户的需求定制。例如:是要轿车,还是越野,车身想要什么颜色,要种款型的;底盘要多高,轮胎的尺寸要多大,统统都由用户去选择,我们要做的就是:根据用户的输入进行拼装,把最终结果呈现给用户就行了。

现在,我们以 改变轮胎的尺寸为例。

既然是根据用户的需求,来设置轮胎的大小那么,肯定是需要传输一个参数的。

import java.util.Scanner;
public class Test {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int size = scanner.nextInt();
        Car car = new Car();
        car.init(size);
    }
}

public class Car {
    public void init(int size){
        Framework framework = new Framework();
        framework.init(size);
    }
}

public class Framework {
    public void init(int size){
         Bottom bottom = new Bottom();
        bottom.init(size);
    }
}
public class Bottom {
    public void init(int size){
        Tire tire = new Tire();
        tire.init(size);
    }
}
public class Tire {
    public void init(int size){
        System.out.println("tire="+size);
    }
}

此时,大家可以想象,只是添加一个功能,全部程序都要修改。如果 产品经理,不是一次性的说,而是分几次说呢? 结果显然易知,整个代码都在不停的进行整改。

这就是 耦合性强的代码 所带来的 缺陷:动一点代码,整体的代码都需要改

上述代码还只是最简单的一种。那么,如何让代码之间进行解耦合,让 代码之间的影响降为零?
答案: 控制反转
        将 关于的对象创建 的权限 交给 “别人 (Spring)我们不再去关注 什么时候去 new 对象,也不需要关注 调用方法 能不能接收多个参数直接告诉 loC 容器,我们需要使用这个类,然后,容器把这类给你,我们直接使用就可以了。调用方法,传参即可。
        此时,我们只需要将原来由自己创建的下级类,改为传递的方式,也就是注入的方式,因为我们不需要在当前类中创建下级类了,所以下级类即使发生变化(创建或减少参数)当前类本身也无需修改任何代码,这样就完成了程序的解耦。PS: 解耦指的是解决了代码的耦合性,耦合性也可以换一种叫法叫程序相关性。好的程序代码的耦合性是很低的,也就是代码之间要实现解耦

 

public class Test {
    public static void main(String[] args) {
        Tire tire = new Tire(20);
        Bottom bottom = new Bottom(tire);
        Framework framework = new Framework(bottom);
        Car car = new Car(framework);
        car.init();
    }
}

public class Car {
    private Framework framework; 
    public void Car(Framework framework){
       this.framework = framework;
    }
    public void init(){
        framework.init();
    } 
}

public class Framework {
    private Bottom bottom;
    public Framework( Bottom bottom){
        this.bottom = bottom;
    }
    public void init(){
        bottom.init();
    }
}
public class Bottom {
    private  Tire tire;
    public Bottom( Tire tire ){
        this.tire=tire;
    }
    public void init(){
        tire.init();
    }
}
public class Tire {
    int size;
    public  Tire( int size){
        this.size=size;
    }
    public void init(){
        System.out.println("tire="+size);
    }
}

上诉的这种 解耦操作,就是运用 IoC 思想。
将 创建类的对象,以及传参的权限,交由“其它人”,自己不再插手其中。
只是在使用的时候,告诉 容器 需要使用某某对象,然后容器就把对应的对象给我们。
最后,我们拿着对象直接使用即可。
至于 对象什么时候创建,几个参数?都不需要我们去操心。
修改起来,也非常简单!
你改了哪个类,你就只针对那个类进行修改就行了。
其它程序,不会受到任何影响!!! 

总结

由此,不难得出结论。
IoC 的优点:
1、实现代码的解耦合,使用代码之间互不影响。
2、对象(Bean)的生命周期,交给 IoC 框架来维护,作为程序员无需再关注了。

举个例子:下馆子 VS 在家自己DIY
        如果我们自己在家做一道菜,我们需要买菜,洗菜,jian菜;另外,我们还需要准备柴米油盐;最后,还要进行一些列的操作,才能做出一道菜。

        但如果是下馆子,你只需要跟老板说 想吃什么。然后,我们就什么都不用管了!等着老板端上来就行了! 菜上来了,直接吃就行了。

这不就是 IoC 思维,将 做饭的权限 交给 其他人 来负责。
我们不需要再去关注过程,直接享用结果即可!

理解 Spring IoC

回到我们的主题:
Spring 是包含了多个⼯具⽅法的 IoC 容器,这就是对 Spring 最核⼼的总结。
集成多个⼯具⽅法”这事咱们以后慢慢再讲.
既然理解了 容器 与 IoC 的意义。
那如何理解“Spring 是⼀个 IoC容器”这句话呢?

我们可以直接认为 Spring 就是一个 IoC 容器。
既然它是一个容器,那么,容器主要的两个核心功能,肯定是具有的!
1、装东西:那些被 控制反转 的对象(Bean),都可以存储在 Spring 中。

2、取东西:将 对象(Bean),从 Spring 中 取出来。

这也是 Spring IoC 容器 最核心的两个功能【存 和 取 】。

对于我们程序员来说,操作 Spring,最最核心的两件事,就是 存 和 取。
初级目标
存:将 Bean(反转的对象),存入 Spring 中。
取:从 Spring 中,取出 Bean(对象)
高级目标
将 Bean(对象)的存取过程,简化,
让其易用性更强!
学习 Spring,就是学习 如何更简单的 进行 存取 操作。

DI

在 讲完了 IoC 的定义之后,我们不得不提一下 Spring 的 另一个定义:DI。
这么说吧:谈到IoC,Spring 是绝对不能少的!而谈到 Spring,DI 是必不可少的!

DI: dependency Injection(依赖注入)

dependency,这个词,相信大家并不陌生!
就是我们 在 pom.xml 中 引入依赖的时候,需要用到的标签。

 dependency Injection(依赖注入)

依赖:
在执行 B 的时候,需要用到 A 类,不然 B 类 无法往下继续执行。

此时,就可以认为 B 类 是 依赖于 A 类的。

注入 :
就是将一个东西 拿过来用,就是注入。
合起来,DI 的意思,就是 引入的依赖,直接拿过来用。

更严格来说:
所谓依赖注⼊,就是由 IoC 容器在运⾏期间,动态地将某种依赖关系注⼊到对象之中。
所以,依赖注⼊(DI)和控制反转(IoC)是从不同的⻆度的描述的同⼀件事情,就是指通过引⼊ IoC 容器,利⽤依赖关系注⼊的⽅式,实现对象之间的解耦。​​​​​​​

 IoC 和 DI,在广义角度上,都是一回事!

这个时候,就会有一个问题,并且,还是一个非常经典的面试题!

IoC 是一种思想,而 DI 是一种实现。

假设,我们有一天心情非常好!决定下班之后,吃顿好的。这就是一种思想.
但是!我们有说要吃什么吗?很明显是没有的!IoC,就是这样的。
我把权限交由 Spring,当我需要使用某个对象的时候,直接向它要。
这对象怎么给我的,我不管!我只关注:是否能拿到这个对象。

而 DI 就是一个具体实现:我准备下班去吃海底捞。
此时,吃什么,是不是就明确落实了!吃海底捞,就是具体的实现。
DI 关注于 怎么将 依赖 注入 对应的对象里面。

IoC 和 DI 之间的关系,就好比多线程进阶中的 乐观锁 和 CAS 之间的关系。
乐观锁:认为进行加锁操作之后,没有那么容易就会发生锁冲突。【思想】
CAS:compare and swap(比较 与 交换)【具体实现】

总结

1、Spring 是什么?如何理解 Spring?

Spring 是一个包含 众多工具方法 的 IoC 容器。
既然 Spring 是一个 IoC 容器(反转控制容器)。
Spring是 存储 IoC【反转控制(后的对象)】 的一个容器。

2、IoC 和 DI 是什么?有什么区别?

IoC - Inversion Of Control(控制反转)
主要是将 对象的权限(创建与销毁)交由 Spring 来管理。
程序员 不必再去 new 对象了!
在使用到某个对象的时候,直接向 Spring 索取,直接使用即可。

DI - dependency injection(依赖注入)
将 引入的依赖 (执行所依赖的对象),拿过来使用。

区别:
IoC 是一种 思想。
DI 是具体的实现。

3、Spring最核心的功能是什么?

既然 Spring 是一个容器,那么,肯定是具有容器的两个核心功能(存 和 取)。
1、将 Bean(反转的对象)存储到 Spring 容器中。
2、将 Bean(反转的对象)从 Spring 容器中取出来。
这也就是 Spring 的 两个核心功能。

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

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

相关文章

从C语言到C++_22(继承)多继承与菱形继承+笔试选择题

目录 1. 继承 1.1 继承的概念 1.2 继承的定义格式 1.3 访问限定符和继承方式 1.4 继承中的赋值 1.5 继承中的作用域 2. 子类(派生类)的默认成员函数 2.1 子类的构造函数 2.2 子类的拷贝构造函数 2.3 子类的赋值重载 2.4 子类的析构函数 2.5 小总结 3. 继承与友元…

欧洲运输业的创新能力评估报告(英)(附下载)

5月,联合研究中心(JRC)在交通研究与创新监测与信息系统(TRIMIS)上发布了一份报告,提供了对欧盟运输部门创新能力的最新评估。TRIMIS通过欧盟层面的宏观指标分析,对运输创新能力进行定期评估。 该报告分析了研究与开发(…

Tuxera NTFS2023Mac电脑免费U盘硬盘读写工具

Mac用户在使用NTFS格式移动硬盘时,会遇到无法写入硬盘的情况。要想解决无法写入的问题,很多人选择使用Mac读写软件。面对市面上“众多”的读写硬盘软件,用户应该怎么选择呢?初次接触移动硬盘的伙伴可能不知道移动硬盘怎么和电脑连…

探析ModaHub魔搭社区中文文本生成图片AI模型的现状、趋势和未来发展方向

目录 一、现状分析 二、趋势分析 三、未来预测 ModaHub魔搭社区是一个专注于AI模型开发和分享的平台,其中文本生成图片AI模型是其中的一个重要领域。本文将通过对ModaHub魔搭社区中文文本生成图片AI模型排行榜的数据分析,来探讨该领域的现状、趋势和未…

Linux安装nginx 反向代理 负载均衡 动静分离 高可用等使用

随着软件需求的发展,现在很多的系统都需要保证高可用、高并发,在此需求之下就需要部署的服务能够不间断的提供服务即避免单点故障问题因此系统需要做集群部署同时还能提升qps、tps等指标;集群部署后的服务就需要对用户的请求能够负载均衡&…

12 通用同步异步收发器(USART)

目录 通用同步异步收发器(USART) 理论部分 USART概览 STM32和PC通信模型 STM32和PC通过RS-232标准通信 RS-232标准介绍 RS-232协议电平标准对比 RS-232标准的物理接口规定及接口标号 RS-232标准下接口标号的作用 RS-232标准数据传输协议层 协议…

探索数字化前沿:数字化产品引领科技创新风潮

随着数字化时代的到来,国内数字化产品市场蓬勃发展,涌现出许多引领行业变革的产品。本文将介绍几个在数字孪生和人工智能领域取得突破的国内产品,带大家了解数字化产品的创新应用和影响力。 山海鲸可视化:山海鲸可视化是一款强大…

Linux 常用命令记录

Linux(Ubuntu) 常用命令的总结 总结工作中用到的ubuntu命令,和添加一些常见的Linux的命令; 1.文件操作&常见命令操作 前置补充:Linux 终端提示符 && 命令语法 Centos[rootoldboy_python ~] ## [用户名主机机器名 路径] 提示符# 用户名 ro…

《计算机系统与网络安全》 第十章 防火墙技术

🌷🍁 博主 libin9iOak带您 Go to New World.✨🍁 🦄 个人主页——libin9iOak的博客🎐 🐳 《面试题大全》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~&#x1f33…

Three.js快速入门

Three.js快速入门 1、threejs文件包下载和目录简介 下载地址: 网盘链接:https://pan.baidu.com/s/1_Ix8TiOScypNcQe3BIl5vA?pwdrrks 提取码:rrksthreejs文件资源目录介绍 three.js-文件包 └───build——three.js相关库,可以引入你的.html文件中…

Frida遍历启动App所有Activity/Service

说明:仅供学习使用,请勿用于非法用途,若有侵权,请联系博主删除 作者:zhu6201976 一、需求 在一些大型App中,往往注册了大量的Activity和Service,这在App的AndroidManifest.xml文件可以清晰呈现。…

Centos7完整安装

一、前言 由于使用VMware workstation使用典型安装以及默认安装方式进行安装的Centos多存在组件不足的问题,这使得使用上述方式进行安装的系统在一些特定情况下需要安装组件,致使系统不是很便利,本文提供了在VMware workstation下进行完整安装…

Verdi之nTrace/nSchema

目录 3.nTrace介绍 3.1 启动Verdi 3.2查看Verdi中的设计结构 3.3查看Verdi中的验证结构 3.4 查找模块和trace信号 3.5 查找string 3.6 信号drive/load 3.7 快速查看设计有哪些信号 4 nSchema 4.1 如何打开原理图 4.2 如何查找 nShema window中器件的源码 4.3 如何显示原理…

【Java面试题】框架篇——Redis

文章目录 Redis的使用场景Redis支持的数据类型如何在Redis中实现分布式锁Redis和Mysql的事务有什么区别?Redis缓存穿透如何解决?Redis缓存雪崩如何解决?什么是缓存击穿,如何解决?Redis是单线程模式的,为什么…

chatgpt赋能python:Python超大数计算

Python超大数计算 介绍 在日常编程中,我们常常需要处理大量数据。这些数据可以是普通的整数或浮点数,但有时候我们需要计算的数据可能会超出计算机处理的数值范围。这时,我们需要使用更为高级的算法来进行超大数计算。 Python语言因为其简…

【Java】 Java 中处理 null 或缺失数据

本文仅供学习参考! 相关教程地址: https://juejin.cn/post/7234924083842154556 https://cloud.tencent.com/developer/article/1107739?areaSource106005.3 https://www.developer.com/java/null-data-java/ 将某些内容表示为空白或不存在始终是编程中…

TX Text Control 31 sp3 for ActiveX-VB6-Crack

Visual Basic 6 应用程序的文档处理 适用于 Visual Basic 6 和基于 COM 的语言的综合文字处理和报告 视窗用户界面 功能齐全的文档编辑器 TX Text Control 是一款免版税、完全可编程的丰富编辑控件,它在专为 Visual Studio 设计的可重用组件中为开发人员提供了广泛的…

数字空间【高校版】上线

WRITE-BUG团队一直在致力于推动科技创新与科研学习数字化建设,为学生的学习、老师的工作,插上数字化的翅膀。 目前,我们注意到高校在大力推进数字化建设,在内容管理上遇到以下问题亟待解决: 各个科研实验室资料、项目…

【后端面经-Java】Synchronize和ReentrantLock区别

【后端面经-Java】Synchronize和ReentrantLock区别 1. 概念介绍1.1 线程安全锁1.2 公平锁1.3 响应中断/等待可中断 2. 区别2.1 底层实现2.2 锁的用法2.3 锁的特点2.4 性能比较2.5 适用场景 3. 总结比较参考文献 1. 概念介绍 1.1 线程安全锁 Synchronize(同步锁&am…

Spring Boot 中的 @PutMapping 注解是什么,原理,如何使用

Spring Boot 中的 PutMapping 注解是什么,原理,如何使用 在 Spring Boot 中,PutMapping 是一种注解,它可以将 HTTP PUT 请求映射到指定的处理方法上。本文将介绍 PutMapping 的原理以及如何在 Spring Boot 中使用它。 PutMapping…