什么是IoC
IoC,(Inversion of Control),即控制反转。那么究竟什么是控制反转?网络上面搜索这个问题,可以搜索到一大堆的新概念、名词,有的甚至直接从官网机器翻译后贴出来,反而让人更晕。
要理解控制反转,那么首先要知道什么是”正常的”控制。先是有正常的控制,然后才会有“反转”的概念,对吧?
房东控制房屋
例如,现在有一个房东,手上有A、B、C三套房子需要出租。
定义一个房子的接口:
public interface House {
/**
* 每一个房子都必须有一个房屋描述
*/
public String describe();
}
里面有一个describe的方法,即房屋描述。
下面有A、B、C三套房子:
房子A
public class HouseA implements House{
private String description = "双层挑高入户大堂,园林设计独一无二";
@Override
public String describe() {
return description;
}
}
房子B
public class HouseB implements House{
private String description = "高层住宅+洋房,打造复合型低密院落";
@Override
public String describe() {
return description;
}
}
房子C
public class HouseC implements House {
private String description = "毗邻千亩湿地公园,5分钟距离接驳多家名校";
@Override
public String describe() {
return description;
}
}
那么,一般的情况是,由房东来选择一套房子进行描述:
public class Landlord {
public void advertise() {
House house = new HouseA();
System.out.println(house.describe());
}
}
可以看到,房东选择了房子A来进行描述,那么在租户那里:
public class Tenant {
public static void main(String[] args) {
Landlord landlord = new Landlord();
landlord.advertise();
}
}
可以看到,对于租户来说,他遇到了一个房东,然后房东向他推销房子A。在这种情况下,租户能够看到哪套房子的决定权,或者说控制权,在房东的手中。
控制反转到租户手中
那么,现在问题来了。如果租户是一个很有主见的人,或者说他希望选房的控制权掌握在自己的手中,即“不要告诉我有哪样的房子,我会告诉你我需要什么样的房子”。此时,由租户决定想租什么样的房子后告诉房东,然后房东再按照租户的需求拿出房子。
那么,对于房东类来说,之前的构造方式:
House house = new HouseA();
一定没法用了。
因为现在的控制权在租户手中,房东现在并不知道租户要哪一套房子,所以自己不能主动的去“创建”一套房子,而是根据租户的需求来“创建”房子。
而房子,作为目前需求中租户所依赖的物品,被称为“依赖对象”。这个词其实很好理解,比如我是一个刚毕业的大学生,我要居住,我要生活,而这些都需要“依赖”房子这个东西。在Java的世界里,“万物皆对象”,所以房子在这里被称为“依赖对象”。
所以,现在的依赖对象(即房子)对于房东来只是作为一个参数传入,而非先前的主动构造,即:
public class Landlord {
House house;
public Landlord(House house) {
this.house = house;
}
public void advertise(House house) {
System.out.println(house.describe());
}
}
那么现在在租户那里,是由他来选择哪套房去创建,假如租户现在需要房子B的信息:
public class Tenant {
public static void main(String[] args) {
House house = new HouseB();
Landlord landlord = new Landlord(house);
landlord.advertise();
}
}
假设租户需要房子C的信息:
public class Tenant {
public static void main(String[] args) {
House house = new HouseC();
Landlord landlord = new Landlord(house);
landlord.advertise();
}
}
由此可以发现,房子还是那三套房子,先前是由房东控制获取哪一套,现在是由租户控制获取哪一套。获得依赖对象的过程被反转了,这就叫“控制反转”。
控制反转,就是获得依赖对象的过程被反转。
控制反转是思想,Spring Framework实现了这种思想
有人可能要问了,这与Spring Framework有什么关系?当然与Spring Framework没有任何关系。控制反转只是一种思想,而Spring Framework是现实了这种思想。你也可以自己编写一套框架,去实现控制反转;或者哪天Spring宣布新版本不再实现控制反转(当然这不太可能,哈哈)。所以千万不要把控制反转和Spring Framework强联系起来,他们只是一个是思想、而一个现实了这种思想的关系。
所以,人家面试官面试的时候问“Spring Framework是什么”的时候,千万不要再回答“Spring就是IoC和AOP”;或者,人家问“控制反转是什么”的时候,千万不要再回答“控制反转是Spring Framework的两大特性之一”。
构造器注入和setter注入
刚才Landlord(房东)类中注入House(房子)类的方式,叫构造器注入,即利用Landlord类的构造方法注入房子。
下面这种方式,叫setter注入,即利用Landlord类的setter方法注入:
public class Landlord {
House house;
public void setHouse(House house) {
this.house = house;
}
public void advertise() {
System.out.println(house.describe());
}
}
然后在用户类中,进行setter注入:
public class Tenant {
public static void main(String[] args) {
House house = new HouseC();
Landlord landlord = new Landlord();
landlord.setHouse(house);
landlord.advertise();
}
}
可以看出,两种方式实现的方法不同,但是本质思想是一样的。
这里,只讲定义,后面会详细阐述这二者间的区别和使用。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。