IOC 原理
SpringIOC实现原理
1. 依赖倒置
假设我们设计一辆汽车:先设计轮子,然后根据轮子大小设计底盘,接着根据底盘设计车身,最后根据车身设计好整个汽车。这里就出现了一个“依赖”关系:汽车依赖车身,车身依赖底盘,底盘依赖轮子。

这样的设计看起来没问题,但是可维护性却很低。假设设计完工之后,上司却突然说根据市场需求的变动,要我们把车子的轮子设计都改大一码。这下我们就蛋疼了:因为我们是根据轮子的尺寸设计的底盘,轮子的尺寸一改,底盘的设计就得修改。
同样因为我们是根据底盘设计的车身,那么车身也得改,同理汽车设计也得改——整个设计几乎都得改!我们现在换一种思路。我们先设计汽车的大概样子,然后根据汽车的样子来设计车身,根据车身来设计底盘,最后根据底盘来设计轮子。这时候,依赖关系就倒置过来了:轮子依赖底盘, 底盘依赖车身, 车身依赖汽车。

这时候,上司再说要改动轮子的设计,我们就只需要改动轮子的设计,而不需要动底盘,车身,汽车的设计了。这就是依赖倒置原则——把原本的高层建筑依赖底层建筑“倒置”过来,变成底层建筑依赖高层建筑。高层建筑决定需要什么,底层去实现这样的需求,但是高层并不用管底层是怎么实现的。这样就不会出现前面的“牵一发动全身”的情况。
2. 控制反转(Inversion of Control)
就是依赖倒置原则的一种代码设计的思路。具体采用的方法就是所谓的依赖注入(Dependency Injection)。其实这些概念初次接触都会感到云里雾里的。说穿了,这几种概念的关系大概如下:

为了理解这几个概念,我们还是用上面汽车的例子。只不过这次换成代码。我们先定义四个Class:车、车身,底盘,轮胎。然后初始化这辆车,最后跑这辆车。代码结构如下:

这样,就相当于上面第一个例子,上层建筑依赖下层建筑——每一个类的构造函数都直接调用了底层代码的构造函数。假设我们需要改动一下轮胎(Tire)类,把它的尺寸变成动态的,而不是一直都是30。我们需要这样改:

由于我们修改了轮胎的定义,为了让整个程序正常运行,我们需要做以下改动:

由此我们可以看到,仅仅是为了修改轮胎的构造函数,这种设计却需要修改整个上层所有类的构造函数!在软件工程中,这样的设计几乎是不可维护的——在实际工程项目中,有的类可能会是几千个类的底层,如果每次修改这个类,我们都要修改所有以它作为依赖的类,那软件的维护成本就太高了。所以我们需要进行控制反转(IOC),及上层控制下层,而不是下层控制着上层。
我们用依赖注入(Dependency Injection)这种方式来实现控制反转。所谓依赖注入,就是把底层类作为参数传入上层类,实现上层类对下层类的“控制”。这里我们用构造方法传递的依赖注入方式重新写车类的定义:

这里我们再把轮胎尺寸变成动态的,同样为了让整个系统顺利运行,我们需要做如下修改:

看到没?这里我只需要修改轮胎类就行了,不用修改其他任何上层类。这显然是更容易维护的代码。不仅如此,在实际的工程中,这种设计模式还有利于不同组的协同合作和单元测试:比如开发这四个类的分别是四个不同的组,那么只要定义好了接口,四个不同的组可以同时进行开发而不相互受限制。
对于单元测试,如果我们要写Car类的单元测试,就只需要Mock一下Framework类传入Car就行了,而不用把Framework、Bottom、Tire全部new一遍再来构造Car。这里我们是采用的构造函数传入的方式进行的依赖注入。其实还有另外两种方法:Setter传递和接口传递。这里就不多讲了,核心思路都是一样的,都是为了实现控制反转。

3. 控制反转容器(IOC Container)
其实上面的例子中,对车类进行初始化的那段代码发生的地方,就是控制反转容器。

显然你也应该观察到了,因为采用了依赖注入,在初始化的过程中就不可避免的会写大量的new。这里IOC容器就解决了这个问题。这个容器可以自动对你的代码进行初始化,你只需要维护一个Configuration(可以是xml可以是一段代码),而不用每次初始化一辆车都要亲手去写那一大段初始化的代码。这是引入IOC Container的第一个好处。IOC Container的第二个好处是:我们在创建实例的时候不需要了解其中的细节。在上面的例子中,我们自己手动创建一个车instance时候,是从底层往上层new的:

这个过程中,我们需要了解整个Car/Framework/Bottom/Tire类构造函数是怎么定义的,才能一步一步new注入。而IOC Container在进行这个工作的时候是反过来的,它先从最上层开始往下找依赖关系,到达最底层之后再往上一步一步new(有点像深度优先遍历):

作者:窜天猴Plus
链接:https://www.jianshu.com/p/ad05cfe7868e
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
IOC 原理的更多相关文章
- Java反射机制及IoC原理
一. 反射机制概念 主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义.在java中,只要给定类的名字, 那么就可以通 ...
- 【Spring】Spring IOC原理及源码解析之scope=request、session
一.容器 1. 容器 抛出一个议点:BeanFactory是IOC容器,而ApplicationContex则是Spring容器. 什么是容器?Collection和Container这两个单词都有存 ...
- IOC原理分析
IOC(inversion of control)控制反转 在我们的程序中,要实现某个功能,我们都会用到两个或两个以上的类来协同完成,那么在一个类中,我们就会要有它的合作类的引用,也就是说这个类依赖于 ...
- Spring的IOC原理[通俗解释一下]
Spring的IOC原理[通俗解释一下] 1. IoC理论的背景我们都知道,在采用面向对象方法设计的软件系统中,它的底层实现都是由N个对象组成的,所有的对象通过彼此的合作,最终实现系统的业务逻辑. 图 ...
- spring原理案例-基本项目搭建 03 创建工程运行测试 spring ioc原理实例示例
下面开始项目的搭建 使用 Java EE - Eclipse 新建一 Dynamic Web Project Target Runtime 选 Apache Tomcat 7.0(不要选 Apache ...
- Spring之IOC原理及代码详解
一.什么是IOC 引用 Spring 官方原文:This chapter covers the Spring Framework implementation of the Inversion of ...
- 1.IOC原理模拟
Spring两大核心功能,IOC(Inverse of Control) 和 AOP(Aspect-Oriented-Programming) IOC原理模拟: 有这样一个beans.xml: ...
- 【SpringBoot】 理解Spirng中的IOC原理
前言 前文已经介绍了Spring Bean的生命周期,在这个周期内有一个重要的概念就是: IOC容器 大家也知道IOC是Sping 的重要核心之一,那么如何理解它呢,它又是产生什么作用呢?本文就IOC ...
- Spring IOC原理补充(循环依赖、Bean作用域等)
文章目录 前言 正文 循环依赖 什么是循环依赖? Spring是如何解决循环依赖的? 作用域实现原理以及如何自定义作用域 作用域实现原理 自定义Scope BeanPostProcessor的执行时机 ...
- Spring IOC 原理深层解析
1 Spring IOC概念认识 1.1 区别IOC与DI 首先我们要知道IOC(Inverse of Control:控制反转)是一种设计思想,就是 将原本在程序中手动创建对象的控制权,交由Spri ...
随机推荐
- 最新通达OA-getshell 漏洞复现
0x00 通达简介 通达OA国内常用的办公系统,使用群体,大小公司都可以,其此次安全更新修复的高危漏洞为任意用户登录漏洞.攻击者在远程且未经授权的情况下,通过利用此漏洞,可以直接以任意用户身份登录到系 ...
- YApi——手摸手,带你在Win10环境下安装YApi可视化接口管理平台
手摸手,带你在Win10环境下安装YApi可视化接口管理平台 YApi YApi 是高效.易用.功能强大的 api 管理平台,旨在为开发.产品.测试人员提供更优雅的接口管理服务.可以帮助开发者轻松创建 ...
- 12. oracle 常用函数
一.字符函数字符函数是oracle中最常用的函数,我们来看看有哪些字符函数:lower(char):将字符串转化为小写的格式.upper(char):将字符串转化为大写的格式.length(char) ...
- Spring Boot系列(四):Spring Boot源码解析
一.自动装配原理 之前博文已经讲过,@SpringBootApplication继承了@EnableAutoConfiguration,该注解导入了AutoConfigurationImport Se ...
- SQL联结笔记(内联结,自联结,自然联结,外联结区别以及应用)
SQL中有三种联结,分别是:内联结,自然联结,外联结. 联结是针对不同表联合起来的一种方式.应用的对象是:表(table) 为了方便验证练习理解,首先展示所要用到的表的内容: 1.Customers表 ...
- MacOS上的效率设置--Windows转移过来的小白设置
1 Copy Path Mac上面的文件管理并不像Windows那么的直观,经常需要指定文件路径时,总是去右键-简介获取相当的费劲.Mac之所以称之为生产力工具,优势就在于此了.利用自动操作的功能就能 ...
- Fiddler或Charles文件转换为Jmeter可执行脚本
解决脚本录制问题,可以将Fiddler或Charles转换成对应的Jmeter脚本,实现部分内容的参数化配置,通过修改部分参数或参数化可以对http协议的接口进行自动化测试或简单的压力测试 GitHu ...
- Java 接口 抽象类 抽象方法
abstract class elehousekeeping { //抽象家用电器类 abstract void opermode(); //抽象方法} class TV extends elehou ...
- Java面试题(Spring Boot/Spring Cloud篇)
Spring Boot/Spring Cloud 104.什么是 spring boot? SpringBoot是一个框架,一种全新的编程规范,他的产生简化了框架的使用,所谓简化是指简化了Spring ...
- flutter 设置状态栏的背景与颜色
flutter 设置状态栏的背景与颜色 导包 import 'dart:io'; import 'package:flutter/services.dart'; 在main()函数中添加以下函数, v ...