一、Spring是什么?
用一句话来概括Spring:Spring是包含了众多工具方法的IoC容器。
那么问题来了,什么是容器?什么是IoC容器?
1、什么是容器?
容器这个词的本身含义就是用来容纳某种物品的装置。
至此,我们目前在Java中接触过的容器有哪些?
- List/Map ….. -> 数据存储的容器
- Tomcat -> Web容器
2、什么是IoC?
IoC = Inversion of Control 中文意思是“控制反转”,也就是说Spring是一个“控制反转”的容器。
如何理解这句话?我们从以下示例描述:
2.1传统的程序开发
假设此时我们需要建造一辆“车”的程序,我们基本的实现思路是:
Car(汽车)-》Framework(车身)-》Bottom(底盘)-》Tire(轮胎)
构建一辆车,车需要依赖于车身,而车身依赖与底盘,底盘又依赖于轮胎,因此,我们要建造一辆车,就需要先去构建车身,想要构建车身,又需要构建底盘,想要构建底盘,又得去构建轮胎~我们目前的实现代码如下:
public class NewCar {
public static void main(String[] args) {
Car car = new Car();
car.init();
}
static class Car{
public void init(){
//依赖车身
Framework framework = new Framework();
framework.init();
}
}
static class Framework{
public void init(){
Bottom bottom = new Bottom();
bottom.init();
}
}
static class Bottom{
public void init(){
Tire tire = new Tire();
tire.init();
}
}
static class Tire{
private int size = 20;
public void init(){
System.out.println("轮胎大小:" + size);
}
}
}
此处我们创建出来的“车”,轮胎大小尺寸是一成不变的,意味着大家的车都是一样的,此时我们考虑一个问题,当对轮胎大小的需求发生改变时将会如何,换句话说,当轮胎的大小是甲方爸爸指定了轮胎大小的话,那么此时,对于轮胎类来说,就需要传入参数进行构建,那么具体如何实现?
此时我们将轮胎的尺寸改为自定义后,可以看到,底盘在构建轮胎的时候,就需要指定轮胎的尺寸,而非是轮胎构建类自己能够决定构建多大尺寸的轮胎,同理,轮胎之上的架构都需要指定轮胎的大小,层层之间的依赖关系过于紧密,此时,传统开发的弊端就显示出来了:当底层的类被修改时,那么整个调用链的所有类都需要被修改,用术语来说,就是耦合性太强了,一个好的程序耦合性是非常低的~
2.2、IoC理念的程序开发
因此,我们需要换种设计思路,有没有一种办法,让上层类调用者不必关心下层所属依赖的变化呢?答案是有的,传统开发理念好比于小作坊式开发,所有的零部件实现都需要亲力亲为,自己去建造自己去使用,那么此时我们所要使用到的设计理念就是工厂化设计理念,我们的将零部件构建交给给个加工商去构建,我们每一步只需要指定需求即可,而不去关心这一层所依赖的下层是如何具体实现的,将各个步骤分离开来,这就是我们IoC的目标–》大大降低各层次之间的依赖程度,从而降级代码之间的耦合性。
具体实现亲看如下代码:
public class IoCNewCar {
public static void main(String[] args) {
Tire tire = new Tire(35);
Bottom bottom = new Bottom(tire);
Framework framework = new Framework(bottom);
Car car = new Car(framework);
car.run();
}
static class Car{
private Framework framework;
public Car(Framework framework){
this.framework = framework;
}
public void run(){
framework.init();
}
}
static class Framework{
private Bottom bottom;
public Framework(Bottom bottom){
this.bottom = bottom;
}
public void init(){
bottom.init();
}
}
static class Bottom{
//用于接收注入的轮胎对象
private Tire tire;
public Bottom(Tire tire){
//注入下层的依赖对象
this.tire = tire;
}
public void init(){
tire.init();
}
}
static class Tire{
private int size;
public Tire(int size){
//实现了尺寸的自定义
this.size = size;
}
public void init(){
System.out.println("轮胎尺寸: " + size);
}
}
}
此时我们构建一辆车,就不是像传统开发的流程一样去做了,而是说,我们先告诉轮胎加工厂商(轮胎类),我们需要一个多大尺寸的轮胎,此时轮胎厂商加工好轮胎之后,交付给底盘加工厂商,此时我们的底盘加工厂商和轮胎加工厂商之间并不需要过多的依赖,只是单纯地将造好的轮胎供给底盘厂商去用,而底盘加工厂商更不必关心轮胎厂商的具体实现,也就是说,无论你轮胎厂商内部如何调整修改,和我(底盘厂商)并没有什么关系,以此类推,直至最上层(Car)。
当我们再次提出新需求的时候,比如说指定轮胎颜色,我们来看看效果:
上层类调用者此时就无需关心轮胎的具体需求变化了,而是说只是使用这么一个依赖关系~我们只需要将原来由⾃⼰创建的下级类,改为传递的⽅式(也就是注⼊的⽅式),因为我们不需要在当前类中创建下级类了,所以下级类即使发⽣变化(创建或减少参数),当前类本身也⽆需修改任何代码,这样就完成了程序的解耦。
在假设除了轮胎以外的部件不需要做出自定义这个功能下,小作坊就好比自定义指令逐级向下传达到轮胎建造者那里,而基于IoC理念的工厂化模式就相当于直接将自定义指令传达到轮胎构建者那里供上层使用~
小结:相比于传统开发的小作坊式生产,IoC的工厂式生产就有以下不同:
1.创建类的顺序发生变化(反转)
2.底层调用类发生改变之后,IoC模式整个调用链上的代码是无需修改的,实现了类与引用类的解耦,这是传统开发所不具备的优势~
3.之前如果要使用依赖类,需要自己创建并管理类的生命周期,IoC无需自己管理对象的生命周期。
总结:
理解Spring IoC:
开篇咱们就讲到:Spring 是包含了多个工具方法的IoC容器。既然Spring是一个IoC容器,重点还是在“容器”二字上,容器所具备的两个最基础的功能:
- 将对象存入到容器
- 从容器中取出对象
换言之,Spring最核心的功能,就是学习如何将对象存入到Spring中,再从Spring中获取对象的过程。Spring是一个IoC容器,说的是对象的创建和销毁权利都交给了Spring来管理了,它本身又具备了存储对象和获取对象的能力。
3、什么是DI?
提到IoC不得不提到的词就是DI,DI是Denpendency Injection的缩写,中文意思是“依赖注入”。
所谓依赖注入,就是由IoC容器在运行期间,动态的将某种依赖关系注入到对象之中。所以,依赖注入(DI)和控制反转(IoC)是从不同的角度描述同一件事情,就是指通过引入IoC容器,利用依赖关系注入的方式,实现对象之间的解耦。
IoC是“目标”,也是一种思想,而目标和思想只是一种指导原则,最终还是要有可行的落地方案,而DI就是属于具体的实现。
二、总结
- Spring是什么?如何理解Spring?
答:Spring是包含了众多工具方法的IoC容器。既然是IoC容器,它就包含两个最基本的概念,把对象存储到Spring当中和从Spring中把对象取出来。
- IoC和DI是什么?有什么区别?
答:IoC指的是“控制反转”,“DI”指的是“依赖注入”,IoC是使用控制反转的思路可以实现类和依赖类之间的解耦,让我们不必再去关心依赖类的具体实现和生命过程,我们只需要使用依赖类时注入其中即可,DI是IOC一种具体实现手段,在程序运行时动态的将对象注入到当前类的实现机制。
- Spring最核心的功能是什么?
答:将对象存入到Spring中,再从Spring中获取对象的过程。Spring是一个IoC容器,说的是对象的创建和销毁权利都交给了Spring来管理了,它本身又具备了存储对象和获取对象的能力。简单来说,就是管理对象,具体来说:把对象能够动态的注册到Spring框架当中,然后再从Spring中取出来。