为什么要控制反转?


原文地址

是什么?

IOC 全称是 Inversion of Control控制反转。按照字面意思理解,将控制反转过来,这里的控制指的是什么?为什么要进行反转,ioc 可以解决什么问题?要回答这些问题,我们需要先了解一下 IOC 为什么会产生。

怎么来的?

Java 是一门面向对象的语言,我们的应用程序通过一个个对象之间的相互关联和作用来完成功能,就像手表里的机械结构。每一个齿轮代表一个对象,对象之间彼此紧密咬合形成一个系统,这样的系统对象之间的耦合度非常高,所谓的耦合度就是关系的依赖程度,高耦合度带来的问题显而易见,只要有一个齿轮发生故障,其它齿轮也无法工作,进而整个系统都无法正常工作,这种牵一发而动全身情况如何才能改善呢?

再来一个 Service 层实际的例子:

public class UserServiceImpl {
    private UserDao userDao = new UserDaoImpl();
    private UserDao userDao = (UserDao)BeanFactory.getBean("userDao");

    public List<User> getAllUser(){
        return userDao.getAllUser();
    }
}

一个是独立控制通过 new 一个 UserDao 实现类来完成,一个是 Bean 工厂通过全限定类名找到 Bean 对象并创建多例对象,无法自主控制。第二者把控制权交给了 Bean 工厂来创建对象,带来的好处就是降低程序间的依赖关系,也叫削减计算机的耦合。

改善方法?

上面机械齿轮的例子可以通过一个中间齿轮的方式来解决,也就是后面的中间 IOC 容器。所有的齿轮都交由中间这个齿轮管理,试着把中间这个齿轮拿掉我们可以看到这两个齿轮之间彼此毫无关系,即使一个齿轮出了故障,也不会影响到其它齿轮。
中间这个齿轮就好比 ioc 容器,其它齿轮就是对象,可以看出引入了 ioc 容器,对象之间的耦合度降低了。当我们修改一个对象的时候不需要去考虑其它对象,因为它不会对其它对象造成影响。

IoC 原理?

这里说到的 ioc 容器到底是个什么东东,又是什么让它具有如此神奇的力量?

先来看一下没有 ioc 容器的时候,对象 A 依赖对象 B,A 在运行到某一时刻的时候会去创建 B 的对象,在这里 A 具有主动权,它控制了对象 B 的创建。

引入 ioc 以后对象 A 和对象 B 之间没有了直接联系,当 A 运行的时候由 ioc 容器创建 B 对象在适当的时候注入到 A 中,在这里,控制权由 A 对象转移到了 ioc 容器。这也就是控制反转名称的由来。

基于上述 UserDao 的例子我们可以通过反射解耦,反射可以根据类的全限定名在程序运行时创建对象,可以这样做,将类的全限定名配置在 xml 文件中,在程序运行时通过反射读取该类的全限定名,动态的创建对象,赋值给 userDao 接口 userDaoImpl。这样做后 UserServiceImpl 和 UserDaoImpl 之间没有了直接的关系,当我们需要替换 UserDaoImpl 对象的时候只需要在配置文件中去修改类的全限定名就可以了,非常的灵活方便,ioc 容器的实现就是这个原理。

IOC 容器可以自动的帮我们完成以上一系列操作,我们需要做的就是通过配置文件告诉 ioc 需要创建哪个类以及类和类之间的关系。

控制反转和依赖注入

在这里需要提到一个概念依赖注入,很多初学者搞不清楚控制反转和依赖注入之间的关系,其实他们是对同一事物的不同角度的描述。
控制反转是一种设计思想依赖注入是这种思想的具体实现

具体说控制反转就是将创建 userDaoImpl 对象的控制权反转过来由 UserServiceImpl 交给了 ioc 容器,强调的是一种能力和思想,ioc 容器具有了控制权。

依赖注入就是 ioc 容器将 UserServiceImpl 所依赖的对象 userDaoImpl,注入给 UserServiceImpl,强调的是一个过程和实现

IOC 很好的体现了面向对象设计法则之一—— 好莱坞法则:“别找我们,我们找你”。

优缺点

  1. 软件系统中由于引入了第三方 IOC 容器,生成对象的步骤变得有些复杂,本来是两者之间的事情,又凭空多出一道手续,所以,我们在刚开始使用 IOC 框架的时候,会感觉系统变得不太直观。所以,引入了一个全新的框架,就会增加团队成员学习和认识的培训成本,并且在以后的运行维护中,还得让新加入者具备同样的知识体系。
  2. 由于 IOC 容器生成对象是通过反射方式,在运行效率上有一定的损耗。如果你要追求运行效率的话,就必须对此进行权衡。
  3. 具体到 IOC 框架产品 (比如:Spring) 来讲,需要进行大量的配制工作,比较繁琐,对于一些小的项目而言,客观上也可能加大一些工作成本。
  4. IOC 框架产品本身的成熟度需要进行评估,如果引入一个不成熟的 IOC 框架产品,那么会影响到整个项目,所以这也是一个隐性的风险。

我们大体可以得出这样的结论:一些工作量不大的项目或者产品,不太适合使用 IOC 框架产品。另外,如果团队成员的知识能力欠缺,对于 IOC 框架产品缺乏深入的理解,也不要贸然引入。最后,特别强调运行效率的项目或者产品,也不太适合引入 IOC 框架产品,像 WEB2.0 网站就是这种情况。

Spring 框架文档:
https://yoyling.com/spring5

本文由 YOYLING. 发表, 最后编辑时间为:2020-09-08 13:02
如果你觉得我的文章不错,不妨鼓励我继续写作。


  TOC