前言
说起Java,就不得不提Spring,提到Spring,就不得不提IOC(控制反转)和AOP(切面), 本章就详细介绍一下IOC思想以及它在Spring中的应用.
概念
IOC:控制反转,一种设计思想,它是Spring的核心。
所谓IOC,对于Spring框架来说,就是由Spring来负责控制对象的生命周期和对象间的关系。
控制反转,由如上的概念,我们可能看到关键词“控制”,那么“反转”好像没有体现出来?
其实不然,“反转”这个东西我们这么理解,有“反转”就有“正转”.所谓的“正转”就是由我们去手动控制对象的生命周期和对象间的关系.当我们把对象的控制权交给Spring时,这就是“反转”.是不是很好理解呢?
为了加深IOC概念的理解,我们举个现实中的简单例子(例子来自网上,个人觉得较为生动,引用之)
我们是如何找女朋友的?常见的情况是,我们去一个个看街上的妹子,然后打听她们的兴趣爱好,联系方式,想办法认识她们,投其所好送其所要,这个过程是复杂深奥的,我们必须自己设计和面对每个环节。
传统的程序开发也是如此,在一个对象中,如果要使用另外的对象,就必须得到它(自己new一个),使用完之后还要将对象销毁(比Connection等),对象始终会和其他的接口或类藕合起来。
那么Spring是如何做的呢?有点像通过婚介找女朋友,在我和女朋友之间引入了一个第三者:婚姻介绍所。
婚介管理了很多男男女女的资料,我可以向婚介提出一个列表,告诉它我想找个什么样的女朋友,比如长得像李嘉欣,身材像林熙雷,唱歌像周杰伦,速度像卡洛斯,技术像齐达内之类的,然后婚介就会按照我们的要求,提供一个妹子,我们只需要去和她谈恋爱、结婚就行了。简单明了,如果婚介给我们的人选不符合要求,我们就会抛出异常。整个过程不再由我自己控制,而是有婚介这样一个类似容器的机构来控制。
码农专属实例
以上如果还不明白的话,我们来敲几行代码助助兴
假设有一个student类,和School类
//学生类
class Student{
private String name;
private Int age;
private School school;
}
//学校类
class School{
private String name;
}
可以看出,Student的类定义是依赖于School类的.
也就是说,当我们想实例化(new)一个Student对象时,就必须new一个School对象,操作如下
Student s1 = new Student();
s1.setName("s1");
s1.setAge(20);
School school = new School();
school.setName("清华池大学");
s1.setSchool(school);
以上的案例只是最简单的一种情况,实际开发中,你会发现,类之间的依赖还是比较多而繁杂的,靠开发自己手动去这么操作,还是挺费劲的.
于是,IOC思想就体现出它的厉害来了,Spring中,所有的类都会在Spring容器中登记,告诉Spring你是个什么东西,你需要依赖什么东西,然后Spring会在系统运行到适当的时候,把你要的东西主动给你,同时也把你交给其他需要你的东西。所有的类的创建、销毁都由Spring来控制,也就是说控制对象生存周期的不再是引用它的对象,而是Spring容器。
对于某个具体的对象比如(Student对象)而言,以前是它(Student对象)控制其他对象(School对象),现在是所有对象(Student对象和School对象)都被Spring容器控制,所以这叫控制反转
DI(Dependency Injection 依赖注入)
细心的朋友,会发现,在刚刚对IOC的解释的例子里,我有提到一个类依赖另一个类的情况,所以类实例化对象时,也必须实例化它依赖的类.
IOC是怎么处理对象间的依赖关系呢?这边就得讲到DI(依赖注入)了.
IOC的一个重点就是在系统运行中,动态的向某个对象提供它所需要的其他对象。这一点是就是通过DI来实现的。
比如对象A需要操作数据库,以前我们总是要在A中自己编写代码来获得一个Connection对象,有了Spring我们就只需要告诉Spring,A中需要一个Connection,至于这个Connection怎么构造,何时构造,A不需要知道。
在系统运行时,Spring会在适当的时候制造一个Connection,然后像打针一样,注射到A当中,这样就完成了对各个对象之间关系的控制。A需要依赖Connection才能正常运行,而这个Connection是由Spring注入到A中的,依赖注入的名字就这么来的。
Spirng IOC案例
我们使用Spring中的@Service和@Autowired注解来写个简单的案例直观的感受IOC
//@Service注解提供控制反转服务
@Service
public class TestService {
public String show() {
return "it is IOC test";
}
}
其它地方,只需要声明变量即可,无需“new”对象,直接使用对象
@Autowired
private TestService testService ;
@RequestMapping(path = {"/testIOC"})
@ResponseBody
public String testAction() {
return "IOC test: " + testService.show();
}
小结
一句话总结IOC: Spring容器管理对象,不用自己“new”对象.