- IOC控制反转
- Ioc - Inversion of Control
- 依赖注入DI
- 依赖注入DI实现控制反转
- IOC DI DL的关系
- 依赖注入的方式
- 依赖倒置原则
- IOC容器的优势
例如Controller, 可以给所有的Controller来设定一个@Controller自定义注解标签, 来标识这个类来处理页面请求的, 同时用@RequestMapping注解来标识这个Controller处理的特定的请求路径. 同时可以设置特定的请求路径和请求方法值, 例如下面的list路径的Get请求方法. DispatcherServlet 在解析Controller的路径的时候, 不需要增加if else, 而是直接通过注解标签就可以通过请求路径和请求方法, 定位到特定的Controller, 这样在增加新的Controller时, 遵循开闭原则, 同时在需要后端服务时, 不需要实例化服务类本身, 即不需要关心细节. 这就是IOC 控制反转.
- IOC控制反转是一个容器.
- 面向对象编程是依赖大量的对象, 而IOC就是将对象的创建, 依赖关系的管理, 以及生命周期交由IOC容器去管理.
- 降低系统在实现上的复杂性和耦合度, 易于扩展, 满足开闭原则.
IOC是Spring Core最核心的部分, 它不是一种技术 , 而是一种思想. 了解IOC需要先知道dependency inversion (DI )
依赖注入DI以设计行李箱为例. 先设计轮子, 再设计底盘 , 箱体, 最后放入行李. 那么依赖关系就是 底盘依赖轮子, 箱体依赖底盘, 行李依赖箱体. 这样设计的缺点就是可维护性低, 如果说轮子修改了, 那么其上层的底盘, 箱体都得改. 代码例如如下: 行李箱Luggage 依赖 箱体, 箱体依赖底盘, 底盘依赖轮子. 每一个类的构造函数, 都直接调用了下层的构造函数
假如要把轮胎的构造函数由写死改成动态的传递int size, 那么要修改的内容如下, 所有的类都要进行修改. 有的类可能是几千个类的底层, 那么要修改起来非常的费劲.
把底层类作为参数传递给上层类, 实现上层对下层的控制. 例如上面的例子改成下面的 , 先设计行李箱, 再设计箱体, 底盘和轮子. 把轮子 底盘箱体注入到上层中去. 代码可以修改为如下, 不用new对象, 而是直接注入对象即可. 这样写也有利于团队合作, 相互只要先定义好要依赖的接口和方法即可, 下面假如要改Tire轮子的方法 那么只需要改Tire轮子即可, 不需要改其他类. 除了使用下面的构造方法来实现依赖注入外, 还有setter传递和接口传递,
IOC是 DL 是一种主动查找的方式, 缺点是代码具有侵入性, 现在基本不用了. DI 是当今IOC主流的实现.
- Setter: 实现类里面成员变量set方法, 来让容器注入依赖的对象
- Interface: 实现特定接口调用, 注入对象
- Constructor: 基于构造函数, 实现特定参数的构造函数,在创建对象时, 将IOC容器注入所依赖的对象,
- Annotation : 通过Java的注解机制, 来让IOC容器注入所依赖的对象. 类似Spring的Autowire一样.
底层依赖于上层. IOC思想最重要的是容器的概念. 上面提到的这些new对象的过程, 都是由控制反转容器做到的, 而不是手动的创建对象.
- 避免在各个地方new 来创建对象, 可以做到统一的维护. 可以是注解, xml. 不需要每次去new对象
- 创建实例的时候, 不需要了解其中的细节
- 结合反射+工厂模式, 满足开闭原则.
- 有人认为IOC容器是简单工厂, 因为其是根据传入值的参数, 获得对象
- 也有人认为是抽象工厂, 毕竟返回值的实例 是不同的对象.
上层依赖于底层时, 创建对象的过程如下, 需要把底层对象一步一步的注入到上层对象中, 需要了解底层的每一个构造方法. 底层依赖于上层时, 创建对象的过程如下, 上层先是通过配置查找底层依赖的对象, 查找到底了, 就把底层对象一步一步注入到上层对象中.
如果要new一个很老的对象, 这个对象依赖了很多的对象, 那么根据IOC, 之前new对象的时候, 前辈已经把要依赖的类注入其中了, 提高了可维护性.