我们通常说的Spring是一个开源框架,它可以让应用程序的开发更加简单。
一句话概括就是:Spring是包含了众多工具方法的IoC容器。
它最核心的功能就是容器管理。
所谓容器,就是一个装物品的器具,比如我们日常生活中的水杯,它是装载水的容器。
在编程中,List、ArrayList、HashMap、线程池.....都可以看做是一个容器。
IoC,是一种设计思想,它的全称是 Inversion of Control ,翻译成中文就是 “控制反转” 的意思。
控制反转:
将创建对象的工作交给容器,此时对象的实例不需要调用者来创建,而是由容器来创建,容器会负责控制程序之间的关系,而不是调用者通过代码控制。
这样,控制权从应用代码转给了容器,控制权发生了反转,这就是控制反转,是Spring的最核心思想之一。
举个例子:
比如我要用程序造一辆车。
那么在造车之前我要先造出车身。
//汽车类
public class Car {
//车身类
private Framework framework;
public Car() {
framework = new Framework();
}
//造车
public void init() {
System.out.println("do Car");
framework.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 = 10;
//造轮胎
public void init() {
//输出轮胎的尺寸
System.out.println("size -> " + size);
}
}
层层创建之后,我们对汽车类的创造过程进行输出:
//汽车类
public class Car {
//车身类
private Framework framework;
public Car() {
framework = new Framework();
}
//造车
public void init() {
System.out.println("do Car");
framework.init();
}
//输出汽车
public static void main(String[] args) {
Car car = new Car();
car.init();
}
}
输出如下:
根据上述的步骤我们造出了一台车,但是这个时候,我想让用户自己定制轮胎的尺寸大小,那么我就要从Car类开始对轮胎的尺寸进行一个输入,然后其他的类也都要依次加上参数的传递。
如下:
//汽车类
public class Car {
private Framework framework;
public Car(int size) {
framework = new Framework(size);
}
public void init() {
System.out.println("do Car");
framework.init();
}
public static void main(String[] args) {
Car car = new Car(15);
car.init();
}
}
//车身类
public class Framework {
private Bottom bottom;
public Framework(int size) {
bottom = new Bottom(size);
}
public void init() {
System.out.println("do Framework");
bottom.init();
}
}
//底盘类
public class Bottom {
private Tire tire;
public Bottom(int size) {
tire = new Tire(size);
}
public void init() {
System.out.println("do Bottom");
tire.init();
}
}
//轮胎类
public class Tire {
public int size = 10;
public Tire(int size) {
this.size = size;
}
public void init() {
System.out.println("size -> " + size);
}
}
此时我们在Car类中进行输入15,此时输出如下:
输出是符合我们预期的,但是我们也可以发现一个问题,我的轮胎类 修改/添加/删除 了一个属性,那么这一系列的类都要进行修改,耦合度很高。
这是因为我们每个类都在内部创建了其依赖的下一个类的对象,也就是说本类对其他类对象进行控制,此时若是这个被控制的对象所对应的类发生了改变,那么本类就也需要对代码进行整改。
而使用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;
private String color = "绿色";
public Tire(int size, String color) {
this.size = size;
this.color = color;
}
public void init() {
System.out.println("size -> " + size + " color -> " + color);
}
}
//输出
public class Test {
public static void main(String[] args) {
Tire tire = new Tire(15, "黄色");
Bottom bottom = new Bottom(tire);
Framework framework = new Framework(bottom);
Car car = new Car(framework);
car.init();
}
}
上面的代码和前面的代码的区别就是:使用IoC思想,将依赖的类通过第三方(Test类)获取到,这样即使依赖的类发生了改变,本类也不需要进行修改,只需要第三方进行修改即可。这就是一个控制权反转的过程。
我们在前面说到 Spring是一个IoC容器,它的重点还是在于容器上面。
所以,Spring IoC的两个最基础的功能就是:将对象存入容器 和 将对象取出容器
Spring IoC的优点:
1. 它可以让代码更加解耦(通过前面的事例代码可以了解到)。
2. 它的使用更加方便(使用一个对象不需要考虑这个对象背后复杂的依赖关系)。
3. 更加高效(类似线程池,依赖的对象不需要每次都进行创建,随用随取,框架已经给我们创建好了)。
提到了IoC,那么就不得不提到DI了,因为他们本身就是一个“关联”的关系。
我们前面说IoC是一种思想,那么DI就是IoC思想的一种具体实现。
DI,全称是 Dependency Injection ,它的意思是 “依赖注入” 。
所谓依赖注入,就是将某种依赖关系动态的的注入(拿到)到对象中。
当我们需要某个依赖时,不需要我们自行创建和调用,而是由Spring框架来帮我们完成,然后注入被调用的依赖,这就是依赖注入。
我们前面举的汽车例子是使用被动的获取对象来实现解耦,这是实现IoC思想的一种方式,而DI就是主动的获取对象来实现解耦,也是实现IoC思想的一种方式。
综上所述,依赖注入(DI)和控制反转(IoC)是从不同角度描述了同一件事情,而DI就是指通过引入IoC容器,利用依赖关系注入的方式,实现了对象之间的解耦。