首先要解决的两个问题。
1.什么是控制反转和依赖注入
2.为什么我们需要控制反转和依赖注入
什么是控制反转和依赖注入
控制反转(Inversion of control) 是一种解耦的思想,它顾名思义,就是控制权的转移,比如项目经理让你改需求,这里就发生了控制权的转移,主要有三步:
1.项目经理要求你添加功能 (这时,控制权在项目经理)
2.你接到通知后开始添加功能需求 (控制权在你手上)
3.交付需求成品(控制权又回到了项目经理)
这样白话的说,那在实际应用中是怎样的?
Ioc 和 di在spring中表现的最为核心出色,我们先看一个Java的例子。
比方说我们现在有两个类,A 和 B
A 类需要依赖于B,那我们说B是A的依赖。
class A{
public String getData(){
B b = new B();
return b.data;
}
}
class B{
public String data = "this is a data";
}
如果要需要B的实例属性data,我们就s
class B{
B(String args){
//...
}
public String data = "this is a data";
}
那么A这个类就彻底毁了,因为当前对B的创建里并没有参数,那么我们需要再去A里添加上这个参数。
但是或许我们可以不必这样做,我们可以把这个恼火的问题甩给顶层开发,也就是我A类的消费者。我只需这样做即可,改变一下A类的声明
class A{
private B b;
A(B b){
this.b = b;
}
public String getData(){
return this.b.data;
}
}
现在我们再次使用A类的时候
A a = new A(new B());
现在,当B类改变构造器参数的时候,我们只需要A类的消费者改变一下A的构造器传值。
比如,现在B类构造函数需要一个字符串作为参数。
A a = new A(new B("this is a string"));
可是现在好像还是不怎么乐观,因为我们仅仅是把责任推给了A类的消费者。
这里仅仅是例子,A类只依赖B,但是在实际开发中,A可能会依赖C、D、E、F…这么多的依赖无疑是给A类的消费者增加工作量,因此,我们需要一个更好的方法来解决这个难题。
我们可以选择工厂设计模式 (factory pattern) 来解决这个难题,我们把解决的事情都交给工厂,现在创建一个工厂,假如A不仅仅依赖于B ,还依赖于C 、D、E
class TempFactory{
public A createA(){
return new A(this.createB(),this.createC(),this.createD(),this.createE());
}
public B createB(){
return new B();
}
public C createC(){
return new C();
}
public D createD(){
return new D();
}
public E createE(){
return new E();
}
}
现在定义了一个工厂来统一管理ABCDE的依赖创建,现在也只有5个对象的创建,好像也不算太坏,但是如果我们有一大堆的对象依赖, 工厂设计模式好像就显得力不从心了,接下来DI登场了。
控制反转和依赖注入是对同一件事情的两个说法
为了实现依赖注入,我们需要有一个Injector(注入器)
在以前,我们是这样做的
现在我们有了依赖注入,我们只需要把注入依赖都交给注入器来完成,实际上整个过程也完成了一次控制反转,这个我们后面再说。
如上图所示,现在我们把A类需要依赖的类都注册进注入器,然后,当A类声明需要它们的时候,注入器就会帮忙注入进来,整个注入的繁琐过程,完完全全不需要我们来管理。
简单说一下这里所发生的控制反转(ioc),原来是A需要B,于是在A中创建B的实例,这里A是主导者,控制权在A上,中间构建了一个注入器,这时,当A需要B的时候,注入器会直接注入进来,这个操作的控制权在注入器上,因为是注入器直接注入的,而不是A主动去创建的,这里A是被动,Injector(注入器)是主动,注入完毕后,控制权又交到了A的手上。
还有一个比较经典的结婚的例子,比如,你年过30,还是一个苦逼的程序员,被生活所迫,需要找一个女朋友,但是你又嫌麻烦,于是你找到了婚介所,你提出你的各种要求,之后你就什么都不用管了,然后婚介所帮你筛选,筛选完毕后,婚介所会通知你过来见面,之后的事情你又可以选择结婚还是不结婚,从Ioc的角度来看,婚介所就是一个注入器,而女朋友是你的依赖,各式各样的woman在婚介所进行注册,完了你去表达你需要的依赖,这时候控制权从你的手上变为婚介所的手上,婚介所进行筛选完毕后,把女朋友注入给你,控制权又交到了你的手上,整个过程就是一个典型的依赖注入。
为什么我们需要控制反转和依赖注入
我觉得上面的例子已经说的很清楚了,因为我们的程序需要的是一种低耦合的设计理念,有了依赖注入和控制反转,我们才能专注于业务逻辑,把这些繁琐的依赖管理交给注入器来完成,并且在整个过程中,耦合性大大的降低。