Spring基础且核心的两大概念——IoC 与 DI

news2024/11/22 6:01:52


什么是Spring?

        Spring 全称 Spring Framework,它是一个目前市场上最流行、结构最庞大的开源框架,之所以如此,是因为其有独特且全面的应用场景,这样好的生态才使企业一直对青睐。

        注意这句话:Spring 是包含了众多思想、工具、方法的的 IoC 容器

什么是容器?

        这里的容器本质上和我们生活中所说的容器基本是一样的,容器就是用来容纳和取出物品的,那么在编程中具体有 List、Map、Set、Vector、Tomcat(Web容器)、Spring等等,它们也可以存入程序员需要的元素,等用的时候再取出来;这一点在 Spring 中表现的淋漓尽致。


IoC控制反转:

        IoC 全称 Inversion of Control 控制反转,是一种设计思想,也是 Spring 中一个核心概念;

        为了更好的解释控制反转,要先从传统的程序设计思想谈起,以下需要引入一个例子:造一辆车,造一辆车需要设计好车身、车身需要建立在底盘上、底盘的设计又依赖轮子的尺寸,那么这四个因素之间相互制约,下面我们来看看具体怎么设计:

先声明好这几个元素:车(Car类)、车身(framework类)、底座(bottom类)、轮子(Tire类)

        传统程序设计:

// 开始设计车子
public class Car {
    private Framework framework; // 先要有车身这个概念

    public Car() {
        framework = new Framework(); // 开始设计车时new出车身
    }
    // 造车子
    public void init() {
        System.out.println("do car");
        framework.init();
    }
    // 测试入口
    public static void main(String[] args) {
        Car car = new Car();
        car.init();
    }
}
// 车身
public class Framework {
    private Bottom bottom; // 先要有底座这个概念

    public Framework() {
        bottom = new Bottom(); //构造车身时创建轮子
    }
    // 造车身
    public void init() {
        System.out.println("do framework");
        bottom.init();
    }
}
// 底座
public class Bottom {
    private Tire tire;  // 先要有轮子的概念

    public Bottom() {
        tire = new Tire(); // 构造底座时创建轮子
    }
    // 造底座
    public void init() {
        System.out.println("do bottom");
        tire.init();
    }
}
// 轮子
public class Tire {
    private int size = 17; // 设计轮子的尺寸
    // 造轮子
    public void init() {
        System.out.println("do tire -> size = " + size);
    }
}

(重要!!!)

        结合代码可以看到,当我开始设计车子的时候,发现需要先有车身,那么我new一个车身,new车身的时候又发现需要先知道底座,那么就去new一个底座,new底座的时候又发现我还需要知道轮子大小,于是再去new轮子。

        这样用的时候才去创建当然很麻烦,另一方便,这种设计思想导致耦合性极强,我需要的这个类可能又受其他类的约束,放在这个例子当中,一旦我想在构造 Tire 实例时,改一下轮子的尺寸,当然需要传入参数 size,怎么传呢?只能是在 new Car(int size) 这种时候去传,那一旦这样去传,其他几个类的构造方法也需要传参了,我又得去修改其他类的代码,岂不是会产生很多麻烦。

为了降低耦合性,我们 Spring 中的 IoC 就起到了效果:

// 设计车子
public class Car {
    private Framework framework;
    
    // 传入车身对象
    public Car(Framework framework) {
        this.framework = framework;
    }

    public void init() {
        System.out.println("do car");
        framework.init();
    }
}
// 车身
public class Framework {
    private Bottom bottom;

    // 传入底座对象
    public Framework(Bottom bottom) {
        this.bottom = bottom;
    }

    public void init() {
        System.out.println("do framework");
        bottom.init();
    }
}
// 底座
public class Bottom {
    private Tire tire;

    // 传入轮子对象
    public Bottom(Tire tire) {
        this.tire = tire;
    }

    public void init() {
        System.out.println("do bottom");
        tire.init();
    }
}
// 轮子
public class Tire {
    private int size = 17;

    // 随时传入参数
    public Tire(int size) {
        this.size = size;
    }

    public void init() {
        System.out.println("tire --> size = " + size);
    }
}
// 测试用例
public class TestCar {
    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();
    }
}

(重要!!!!)

        观察新的代码很容易发现,只是稍微调整了一下每个类的构造方法,之前是我需要时自己new,现在是我需要时别的类给我直接传对象,我自身需要的那个对象直接和传入的对象去做赋值替换即可,如此一来就降低了耦合性,即使轮子的尺寸要改变,也不需要修改其他类的代码了,实质上改变的整个调用链的关系。

        再举一个例子帮助理解:上世纪最初的汽车生产车间中,一个工人可能要负责很多项目的设计、检测、监测,这样就导致工厂招人的难度较高,一个工人要会的多,对于工人可能一会忙这个,一会又要去忙那个,导致生产效率不一定高。后来随着时代发展,工厂改变了思路,实现了流水线生产模式,让一个或多个工人只负责一件事,这样每个环节的工人都各司其职,不受其他环节的影响,便于工厂管理也提高了用人成本和生产效率;

反转体现在哪里?

    上面造车代码中对象的创建顺序:

  • 传统设计过程:Car -> Framework ->Bottom -> Tire;
  • IoC设计过程: Tire -> Bottom -> Framework -> Car;

两种思想导致对象创建和代码执行逻辑刚好发生了反转,这就是反转的亮点!

理解 Spring IoC 的特性:

        上面大篇幅都介绍了 IoC 思想的神奇之处,现在我们把 Spring 和 IoC 结合起来,这才是我们的重点:

        “Spring 是包含了众多思想、工具、方法的IoC容器”

        简言之:Spring 是一个 IoC 容器,所以可以看出 Spring 底层依赖的就是 IoC 思想,同时拥有容器的功能;

  • 将对象存入容器内:相当于把所有要使用的工具都准备好先放到仓库中,包括用完再放回去;
  • 从容器中取出对象:需要什么工具就直接从仓库中和取出来即可;

        为什么这里要强调存和取?因为传统的 new 的过程相当于每次需要的时候才去制作工具,用完了直接就扔了不保存,而在 Spring 中,对象的创建和销毁全都交给 Spring 来管理;


DI依赖注入:

        DI 全称 Dependency Injection,是依赖注入的意思。

        其实 DI 和 IoC 说的是同一件事情,但是用不同的角度去完成,而 IoC 是一种设计思想,DI 是具体实现。

        依赖注入:在 IoC 容器运行期间,动态地将某种依赖关系注入到对象中;

        就像给 maven 项目中配置 pom.xml 文件的过程,也会引入 dependency 依赖,包括给方法传参,类实现接口,这些都是手动注入依赖,而 Spring 的 DI 却可以实现自动、动态的注入依赖。

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

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

相关文章

Vector - 常用CAN工具 - CANoe软件安装常见问题

目录 一、确认电脑系统盘是否满足要求,CANoe软件对PC要求如下: 二、确认软件安装包完整 三、确认软件与电脑系统之间的兼容性 四、关闭后台程序 五、安装软件 六、清空临时文件夹 七、尝试在其他电脑上安装 一、确认电脑系统盘是否满足要求&#…

LLVM代码空间优化(一) 编译器自带的优化选项

最近项目组遇到编译安全固件,超出了r52安全核SRAM自带空间问题。急需要找寻方法优化代码体积(代码段大小数据段大小stackbss段)方法,目前初步分析只有代码段&数据段有优化的可能,bss和stack优化空间并不大。有方法…

Unity Audio -- (5)声音的可用性考量

在某些情况下,用户可能会关闭声音或者让音量降低至很小的水平,用户本身的听力情况(用户可能有听力障碍,失聪等情况)也有差异。一个好的设计者应该要考虑到项目的可用性,音频也不例外。本节我们来看看如何能…

由于找不到msvcr100.dll,msvcr100.dll丢失怎样修复

在我们打开游戏或者软件的时候,电脑提示由于找不到msvcr100.dll文件,无法执行此代码是什么意思?msvcr100.dll为什么会丢失,又该如何修复呢?相信这些问题困扰着不少小伙伴,昨天是准备玩吃鸡游戏的时候&#…

被面试官故意刁难,太难了...

今年的金三银四,我和大多数的同行一样加入了升职涨薪的潮水,我早在2个月前就开始准备,我觉得自己在技术方面完全没有问题,于是这两个月我每天在公司摸鱼2小时,回家刷2小时,前前后后刷了几千到面试题&#x…

【LeetCode困难】1263. 推箱子

「推箱子」是一款风靡全球的益智小游戏,玩家需要将箱子推到仓库中的目标位置。 游戏地图用大小为 m x n 的网格 grid 表示,其中每个元素可以是墙、地板或者是箱子。 现在你将作为玩家参与游戏,按规则将箱子 ‘B’ 移动到目标位置 ‘T’ &am…

设计模式|代理模式

代理模式介绍 ​代理模式指为其他对象提供一种代理,以控制对这个对象的访问。在某些情况下,一个对象若不能直接引用另一个对象,而代理对象可以在客户端与目标对象之间起到中介的作用。 代理模式使用场景 普通代理 普通代理模式是指在代理模…

C++的string类使用介绍

string类 1.为什么要学习string类?1.1.C语言中的字符串1.2. 日常中 2. 标准库中的string类2.2 string类(对于单字节的字符)的常用接口说明①string常见的构造函数②string类对象的容量操作③string类对象的访问以及遍历操作④string类对象的修改操作⑤string类非成员…

OrCAD怎样把原理图输出为DXF格式

OrCAD怎样把原理图输出为DXF格式 又有段时间没分享文章了,想想主要还是自媒体写点内容确实不容易,要不断坚持下来更不容易,一直以来也就是凭着“乐于分享”的心在不定时更新。 今天分享的主题是:OrCAD怎样把原理图输出为DXF格式…

标准CSO

Cheng R, Jin Y. A competitive swarm optimizer for large scale optimization[J]. IEEE transactions on cybernetics, 2014, 45(2): 191-204. 1.1 背景介绍 CSO(competitive swarm optimizer)算法是在PSO(particle swarm optimization&a…

医日健“数智药房”解锁购药新模式

“现在买药这么方便,半夜拉肚子过来自助付款、自助取药,还能连线医生,很快就买好了药。”上海市宝山区消费者王先生惊喜地说。近日,宝山区一国大药房医日健 “智慧药房”正式上线营业,该药房实现自助式、无接触就医购药…

如何添加团队成员到你的项目

本文介绍在YonBuilder移动开发中,如何把你的团队成员添加到你的应用中,让团队成员也具备应用的相关配置,代码拉取,打包编译等功能权限。 简单来说把「团队成员添加到你的项目」,一共需要三步大流程操作,具…

基于AT89C51单片机的篮球比赛计时计分器

点击链接获取Keil源码与Project Backups仿真图: https://download.csdn.net/download/qq_64505944/87778138?spm1001.2014.3001.5503 源码获取 主要内容: 比赛的计分和计时的工具大多是很简陋的比分牌,十分的不方便。而且大多由于缺少24秒…

Meta-learning综述

文章目录 几个概念1)监督、无监督、弱监督学习(Weakly Supervised Learning)以及 自监督学习(Self-supervised Learning)2)域偏移、域适应、域泛化3)N-way K-shot(Few-shot learning…

【Java虚拟机】JVM诊断神器Arthas入门实操

1.Arthas简介快速入门 阿里开源的Java诊断工具,它可以在运行时对Java应用程序进行动态诊断和调试 当你遇到以下类似问题而束手无策时,Arthas可以帮助你解决 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?我改的代…

国考省考行测:数字推理题2

国考省考行测:数字推理题2 2022找工作是学历、能力和运气的超强结合体! 公务员特招重点就是专业技能,附带行测和申论,而常规国考省考最重要的还是申论和行测,所以大家认真准备吧,我讲一起屡屡申论和行测的重要知识点 …

改进YOLOv8 | 特征融合篇 | YOLOv8 应用 BiFPN 结构 | 《 EfficientDet: 可扩展和高效的目标检测》

模型效率在计算机视觉中变得越来越重要。在本文中,我们系统地研究了目标检测中的神经网络架构设计选择,并提出了几种关键的优化方法来提高效率。首先,我们提出了一种加权双向特征金字塔网络(BiFPN),它可以实现简单快速的多尺度特征融合;其次,我们提出了一种复合缩放方法…

从期望最大化(EM)到变分自编码器(VAE)

本文主要记录了自己对变分自编码器论文的理解。 Kingma D P, Welling M. Auto-encoding variational bayes[J]. arXiv preprint arXiv:1312.6114, 2013. https://arxiv.org/abs/1312.6114 1 带有潜在变量的极大似然估计 假设我们有一个有限整数随机数发生器 z ∼ p θ ( z ) …

Linux | 学习笔记(适合小白)上

操作系统概述: 计算机是由硬件和软件这两个主要部分组成的操作系统是软件的一类,主要作用是协助用户调度硬件工作,充当用户和计算机硬件之间的桥梁常见的操作系统:PC端:Windows,Linux,MacOS&…

电子邮件市场中,如何使用您的Gmail?

Gmail凭借其直观的界面、慷慨的免费存储空间(与其他Google工具共享15 GB,如Google Drive和Photos)以及作为常规Gmail账户附加的各种免费生产力工具,在电子邮件市场占据主导地位。但是,人们对Google如何使用您的电子邮件…