首页 > 其他分享 >面试突击73:IoC 和 DI 有什么区别?

面试突击73:IoC 和 DI 有什么区别?

时间:2022-08-25 00:58:38浏览次数:93  
标签:构造方法 DI 对象 init 73 IoC public

IoC 和 DI 都是 Spring 框架中的重要概念,就像玫瑰花与爱情一样,IoC 和 DI 通常情况下也是成对出现的。那 IoC 和 DI 什么关系和区别呢?接下来,我们一起来看。

1.IoC 介绍

IoC 是 Inversion of Control 的缩写,翻译成中文是“控制反转”的意思,它不是一个具体的技术,而是一个实现对象解耦的思想。

要解释什么是解耦?就要了解什么是耦合,所谓的耦合是指:两个或两个以上对象存在依赖,当一方修改之后会影响另一方,那么就说这些对象间存在耦合。而解耦就是解除两个或两个以上对象,修改之后影响另一方的问题。

那 IoC(控制反转)是如何实现解耦的呢?

我们来举一个例子,比如 A 对象中需要使用 B 对象的某个方法,那么我们通常的实现方法是这样的:

class A {
    public void init() {
        // 调用 B 类中的 init 方法
        B b = new B();
        b.init();
    }
}
class B {
    public B() {
    }

    public void init() {
        System.out.println("你好,世界。");
    }
}

然而此时对象 A 和对象 B 是存在耦合的,因为一旦修改了 B 对象构造方法的参数之后,那么 A 对象里面的写法也要跟着改变,比如当我们将构造方法改为以下代码时:

class B {
    public B(String name) {
        System.out.println("姓名:" + name);
    }
    public void init() {
        System.out.println("你好,世界。");
    }
}

此时构造方法已经从原本无参构造方法变成了有参的构造方法,这里不考虑构造方法重载的情况,因为实际业务中,很可能是 B 类的构造方法写错了,忘记加参数了,于是后面又补充了一个参数,此时是不需要对构造方法进行重载的,那么此时,之前对象 A 里面的调用就会报错,如下图所示:
image.png
这就是开发中经常遇到的一个问题,那怎么解决呢?

我们可以通过将对象传递而并 new 对象的方式来解决,如下代码所示:

class A {
    // 先定义一个需要依赖的 B 对象
    private B b;
    // 通过构造方法实现赋值(初始化)
    public A(B b) {
        this.b = b;
    }
    public void init() {
        // 调用 B 类中的 init 方法
        b.init();
    }
}
class B {
    public B(String name) {
        System.out.println("姓名:" + name);
    }
    public void init() {
        System.out.println("你好,世界。");
    }
}

这样改造之后,无论构造方法怎么修改,即使需要加更多的参数,而调用它的 A 类都无需做任何修改,这样就实现了对象的解耦。

那这个解耦的示例和 IoC 有什么关系呢?

IoC 实现的思路和上述示例一样,就是通过将对象交给 Spring 中 IoC 容器管理,在其他类中不直接 new 对象,而是通过将对象传递到当前类的方式来实现解耦的。

小结

在 new 对象的时代,对象的管理权是由当前类控制的,而有了 IoC 之后,对象的管理权就交给非当前类的 IoC 容器管理了,此时对象的管理权就发生了反转和改变,这就是 IoC,这就是控制(权)反转。

2.DI 介绍

DI 是 Dependency Injection 的缩写,翻译成中文是“依赖注入”的意思。依赖注入不是一种设计实现,而是一种具体的技术,它是在 IoC 容器运行期间,动态地将某个依赖对象注入到当前对象的技术就叫做 DI(依赖注入)

在上述示例中,A 类在使用 B 类时,就是通过构造方法将依赖对象 B 引入的,这种实现方法就可以看作是通过构造方法实现依赖注入的手段,具体代码如下:

class A {
    // 先定义一个需要依赖的 B 对象
    private B b;
    // 通过构造方法实现赋值
    public A(B b) {
        this.b = b;
    }
    public void init() {
        // 调用 B 类中的 init 方法
        b.init();
    }
}

3.IoC VS DI

从上面的内容中我们可以看出,IoC 和 DI 虽然定义不同,但它们所做的事情都是一样的,都是用来实现对象解耦的,而二者又有所不同:IoC 是一种设计思想,而 DI 是一种具体的实现技术

比如,磊哥今天心情比较好,想出去吃顿好的,那么“想吃顿好的”就是一种思想、就是 IoC。

但什么才是“好的(饭)”呢?海底捞还是韩式料理?具体吃什么是 DI。

因此“磊哥今天心情比较好,想出去吃顿好的”是一种思想、是 IoC,而吃一顿海底捞而非韩式料理就是具体的实现、是 DI。

总结

IoC 和 DI 都是 Spring 框架中的重要概念,它们都是用来实现对象解耦的,其中 IoC(控制反转)是一种设计思想,而 DI(依赖注入)是一种具体的实现手段。

是非审之于己,毁誉听之于人,得失安之于数。

公众号:Java面试真题解析

面试合集:https://gitee.com/mydb/interview

关注下面二维码,订阅更多精彩内容。
  转 https://www.cnblogs.com/vipstone/p/16570983.html

标签:构造方法,DI,对象,init,73,IoC,public
From: https://www.cnblogs.com/wl-blog/p/16622849.html

相关文章

  • AT4573 题解
    题目传送门小学生又双叒叕来写题解啦!我来介绍一种与众不同的跑得更慢的方法,那就是排序加二分。排序的作用是为了二分,因为二分的前提是数组有序。因此读入完数据后排序......
  • Redis连环问
    Redis连环问Redis为什么这么快呢?基于内存:Redis是使用内存存储,没有磁盘IO上的开销。数据存在内存中,读写速度快。单线程实现(Redis6.0以前):Redis使用单个线程处理请求,避......
  • Redis(6)------通用命令
    Key相关命令在redis中无论什么数据类型,在数据库中都是以Key-value形式保存,通过进行对Redis-Key的操作来完成对数据库中数据的操作。常用命令keys*:查看当前数据库中的所......
  • 【python】numpy数组升维函数expand_dims()
    expand_dims(a,axis),其中a为输入的数组,axis为整型指定要增加的维数位置可以结合shape()来看,shape()返回的是一个tuple,把其看成一个数组并指定下标。如果shape为(1,2),则......
  • es6 findIndex,find用法
    letarr=[{name:'test1',age:1},{name:'test2',age:2},{name:'test3',age:3}]lettemp=arr.findIndex(function(item){console.log(item.name......
  • DiskGenius软件屏蔽硬盘坏道方法
    小编今天在这里教大家如何屏蔽磁盘坏道,往后可能不会出现同样的消息,大家觉得可以动动你的手指转载或者收藏下到了这一步,首先需要说明的是已经使用过工作扫描完磁盘坏道,并且......
  • SV编译器指令(Compiler Directives)
    SystemVerilog提供大量编译器指令来指导代码进程,比如`define、`ifdef、`elsif、`ifndef、`timescale、`default_nettype等。它们前面是(`)字符(重音字符)(不要将其与撇......
  • 【云原生】Kubernetes(k8s)——本地存储卷介绍与简单使用(emptyDir,hostPath,local volume)
    目录一、概述二、emptyDir三、hostPath四、emptyDir和hostPath异同五、localvolume概述(常用)六、StorageClass本地存储(常用)1)创建本地存储类(StorageClass)2)创建PV3)创建PVC4......
  • Redis集群模式搭建
    Redis主要有三种集群方案:主从模式哨兵模式集群模式集群模式搭建Redis3.0版本之后才可用,推荐3主3从集群模式。1.启动6台Redis配置文件如下,redis_7002.conf...类......
  • Codeforces Round #710 (Div. 3) D. Epic Transformation(优先队列)
    https://codeforces.com/contest/1506/problem/D鉴定完毕,这题卡映射数量到优先队列的那一步操作给你一个由整数组成的长度为n的数组a。您可以对阵列应用由几个步骤组成......