如何理解Spring的IOC和DI

发布时间 2023-07-22 22:14:24作者: 禅说编程

学习过Spring框架的人一定都会听过Spring的IoC(控制反转) 、DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IOC 、DI这两个概念是模糊不清的,是很难理解的。今天我就谈谈我对IOC和DI的理解,希望对大家有帮助。

1、IOC与DI介绍

IOC 是 Inversion of Control 的缩写,翻译成中文是“控制反转”的意思。它不是一个具体的技术,而是一种设计思想。

它主要是为了解决程序里对象解耦的。

那什么是解耦呢?要解释什么是解耦,那就得先了解什么是耦合。

所谓的耦合是指:两个或者两个以上的对象存在依赖,当一方修改之后会影响另一方,那就可以说这些对象间存在耦合。

比如对象A中需要使用对象B的某个方法,我们通常的使用方法是这样的:

class A {
	public void run(){
		B b = new B();
         b.run()
	}
}

class B {
	public B(){
		//执行过程省略
	}
	public void run(){
		//执行过程省略
	}
}

现在A对象和B对象就存在耦合,因为如果后面由于业务需求变更,B对象需要传入C对象才可以执行,所以我们不得不修改构造方法,那么A对象的run方法也要做相应的改变。代码改动如下:

class B {
	private C c;
	
	public B(C c){
		//执行过程省略
	}
	public void run(){
		//执行过程省略
	}
}

此时的B的构造方法一定需要传入C对象,那么之前A对象run方法也需要new 一个C对象,传入给B。这是开发中经常遇到的问题,如果只是A对象run用到了B,那么我们改一下就好,但是如果我们有几十处需要new B呢,那么这修改量就特别麻烦。

所以解耦就是为了解决,上述例子的问题,解除对象之间修改后影响另一方的问题。

那我们要怎么解决呢?

我们可以通过将对象传递而不是new对象的方式来解决,比如这样

class A {
	private B b;
	
	public void A(B b){
		this.b = b;
	}
	
	public void run(){
         b.run()
	}
}

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

那么B对象谁来new呢?

答案就是Spring的IOC容器,IOC容器实际上就是一个存放各种对象的map,在项目启动的时候会读取配置文件里面的bean节点或者扫描类上的注解,通过反射new对象放到这map里。当某个对象需要依赖其他对象时,就通过将依赖对象传递给当前对象,这就到达了解耦。而这种技术就是我们所说的DI(依赖注入)。

DI 是 Dependency Injection 的缩写,翻译成中文是“依赖注入”的意思。依赖注入是实现IOC的一种具体技术 ,它是在IOC运行期间,动态的将某个对象注入到当前对象的技术

所以由此我们可以看出,IOC是一种思想,依赖注入是一种具体的实现方式。

2、控制反转与依赖注入的概念理解

那大家可能有疑问,那为什么要叫控制反转呢?

由上述例子可以看出,一开始对象A使用对象B的时候是通过new创建对象的,是A主动去创建依赖对象B。而在引入IOC后,创建对象已经不是由A创建,而是由IOC容器去创建。也就是说,一开始对象B的创建是由A控制的。而当对象B交由IOC容器创建,并注入给A,对象B的创建和注入就由IOC容器控制了,对象A只是被动的接受依赖对象B。

所以控制反正可以理解为,创建对象的控制权进行转移,以前创建对象的主动权和创建时机是由自己控制的,而现在这种权利转移到了第三方。比如转移给了IOC容器。换种说话就是,控制获得依赖对象的方式反转了。

那么依赖注入就好理解了,就是动态的向某个对象提供它所需的其他对象

3、总结

IOC不是什么技术,而是一种设计思想,在spring中,对象的创建和注入是由IOC容器控制的,这就实现了对象控制权的反转。由我们对对象的控制变成了IOC容器对对象的控制。DI是IOC的具体实现。程序把依赖交给容器,容器帮你管理依赖。