在一开始学习 Spring 的时候,我们就接触 IoC 了,作为 Spring 第一个最核心的概念,我们在解读它源码之前一定需要对其有深入的认识,本篇为【死磕 Spring】系列博客的第一篇博文,主要介绍 IoC 基本概念和各个组件。

IOC 理论

IoC 全称为 Inversion of Control,翻译为 “控制反转”,它还有一个别名为 DI(Dependency Injection),即依赖注入。

如何理解“控制反转”好呢?理解好它的关键在于我们需要回答如下四个问题:

  1. 谁控制谁
  2. 控制什么
  3. 为何是反转
  4. 哪些方面反转了

在回答这四个问题之前,我们先看 IOC 的定义:

所谓 IOC ,就是由 Spring IOC 容器来负责对象的生命周期和对象之间的关系

上面这句话是整个 IoC 理论的核心。如何来理解这句话?我们引用一个例子来走阐述(看完该例子上面四个问题也就不是问题了)。

已找女朋友为例(对于程序猿来说这个值得探究的问题)。一般情况下我们是如何来找女朋友的呢?首先我们需要根据自己的需求(漂亮、身材好、性格好)找一个妹子,然后到处打听她的兴趣爱好、微信、电话号码,然后各种投其所好送其所要,最后追到手。如下:

/*** 年轻小伙子*/
public class YoungMan {private BeautifulGirl beautifulGirl;YoungMan(){// 可能你比较牛逼,指腹为婚// beautifulGirl = new BeautifulGirl();}public void setBeautifulGirl(BeautifulGirl beautifulGirl) {this.beautifulGirl = beautifulGirl;}public static void main(String[] args){YoungMan you = new YoungMan();BeautifulGirl beautifulGirl = new BeautifulGirl("你的各种条件");beautifulGirl.setxxx("各种投其所好");// 然后你有女票了you.setBeautifulGirl(beautifulGirl);}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

这就是我们通常做事的方式,如果我们需要某个对象,一般都是采用这种直接创建的方式(new BeautifulGirl()),这个过程复杂而又繁琐,而且我们必须要面对每个环节,同时使用完成之后我们还要负责销毁它,在这种情况下我们的对象与它所依赖的对象耦合在一起。

其实我们需要思考一个问题?我们每次用到自己依赖的对象真的需要自己去创建吗?我们知道,我们依赖对象其实并不是依赖该对象本身,而是依赖它所提供的服务,只要在我们需要它的时候,它能够及时提供服务即可,至于它是我们主动去创建的还是别人送给我们的,其实并不是那么重要。再说了,相比于自己千辛万苦去创建它还要管理、善后而言,直接有人送过来是不是显得更加好呢?

这个给我们送东西的“人” 就是 IoC,在上面的例子中,它就相当于一个婚介公司,作为一个婚介公司它管理着很多男男女女的资料,当我们需要一个女朋友的时候,直接跟婚介公司提出我们的需求,婚介公司则会根据我们的需求提供一个妹子给我们,我们只需要负责谈恋爱,生猴子就行了。你看,这样是不是很简单明了。

诚然,作为婚介公司的 IoC 帮我们省略了找女朋友的繁杂过程,将原来的主动寻找变成了现在的被动接受(符合我们的要求),更加简洁轻便。你想啊,原来你还得鞍马前后,各种巴结,什么东西都需要自己去亲力亲为,现在好了,直接有人把现成的送过来,多么美妙的事情啊。所以,简单点说,IoC 的理念就是让别人为你服务,如下图(摘自Spring揭秘):

在没有引入 IoC 的时候,被注入的对象直接依赖于被依赖的对象,有了 IoC 后,两者及其他们的关系都是通过 Ioc Service Provider 来统一管理维护的。被注入的对象需要什么,直接跟 IoC Service Provider 打声招呼,后者就会把相应的被依赖对象注入到被注入的对象中,从而达到 IOC Service Provider 为被注入对象服务的目的。所以 IoC 就是这么简单!原来是需要什么东西自己去拿,现在是需要什么东西让别人(IOC Service Provider)送过来

现在在看上面那四个问题,答案就显得非常明显了:

  1. 谁控制谁:在传统的开发模式下,我们都是采用直接 new 一个对象的方式来创建对象,也就是说你依赖的对象直接由你自己控制,但是有了 IOC 容器后,则直接由 IoC 容器来控制。所以“谁控制谁”,当然是 IoC 容器控制对象。
  2. 控制什么:控制对象。
  3. 为何是反转:没有 IoC 的时候我们都是在自己对象中主动去创建被依赖的对象,这是正转。但是有了 IoC 后,所依赖的对象直接由 IoC 容器创建后注入到被注入的对象中,依赖的对象由原来的主动获取变成被动接受,所以是反转。
  4. 哪些方面反转了:所依赖对象的获取被反转了。

妹子有了,但是如何拥有妹子呢?这也是一门学问。

  1. 可能你比较牛逼,刚刚出生的时候就指腹为婚了。
  2. 大多数情况我们还是会考虑自己想要什么样的妹子,所以还是需要向婚介公司打招呼的。
  3. 还有一种情况就是,你根本就不知道自己想要什么样的妹子,直接跟婚介公司说,我就要一个这样的妹子。

所以,IOC Service Provider 为被注入对象提供被依赖对象也有如下几种方式:构造方法注入、stter方法注入、接口注入。

构造器注入

构造器注入,顾名思义就是被注入的对象通过在其构造方法中声明依赖对象的参数列表,让外部知道它需要哪些依赖对象。

YoungMan(BeautifulGirl beautifulGirl){this.beautifulGirl = beautifulGirl;
}
  • 1
  • 2
  • 3

构造器注入方式比较直观,对象构造完毕后就可以直接使用,这就好比你出生你家里就给你指定了你媳妇。

setter 方法注入

对于 JavaBean 对象而言,我们一般都是通过 getter 和 setter 方法来访问和设置对象的属性。所以,当前对象只需要为其所依赖的对象提供相对应的 setter 方法,就可以通过该方法将相应的依赖对象设置到被注入对象中。如下:

public class YoungMan {private BeautifulGirl beautifulGirl;public void setBeautifulGirl(BeautifulGirl beautifulGirl) {this.beautifulGirl = beautifulGirl;}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

相比于构造器注入,setter 方式注入会显得比较宽松灵活些,它可以在任何时候进行注入(当然是在使用依赖对象之前),这就好比你可以先把自己想要的妹子想好了,然后再跟婚介公司打招呼,你可以要林志玲款式的,赵丽颖款式的,甚至凤姐哪款的,随意性较强。

接口方式注入

接口方式注入显得比较霸道,因为它需要被依赖的对象实现不必要的接口,带有侵入性。一般都不推荐这种方式。


关于 IOC 理论部分,笔者不在阐述,这里推荐几篇博客阅读:

  • 谈谈对Spring IOC的理解:http://www.cnblogs.com/xdp-gacl/p/4249939.html
  • Spring的IOC原理[通俗解释一下]:https://blog.csdn.net/m13666368773/article/details/7802126
  • spring ioc原理(看完后大家可以自己写一个spring):https://blog.csdn.net/it_man/article/details/4402245

各个组件

先看下图(摘自:http://singleant.iteye.com/blog/1177358)

该图为 ClassPathXmlApplicationContext 的类继承体系结构,虽然只有一部分,但是它基本上包含了 IOC 体系中大部分的核心类和接口。

下面我们就针对这个图进行简单的拆分和补充说明。

Resource体系

Resource,对资源的抽象,它的每一个实现类都代表了一种资源的访问策略,如ClasspathResource 、 URLResource ,FileSystemResource 等。

有了资源,就应该有资源加载,Spring 利用 ResourceLoader 来进行统一资源加载,类图如下:

BeanFactory 体系

BeanFactory 是一个非常纯粹的 bean 容器,它是 IOC 必备的数据结构,其中 BeanDefinition 是她的基本结构,它内部维护着一个 BeanDefinition map ,并可根据 BeanDefinition 的描述进行 bean 的创建和管理。

BeanFacoty 有三个直接子类 ListableBeanFactoryHierarchicalBeanFactory 和 AutowireCapableBeanFactoryDefaultListableBeanFactory 为最终默认实现,它实现了所有接口。

Beandefinition 体系

BeanDefinition 用来描述 Spring 中的 Bean 对象。

BeandefinitionReader体系

BeanDefinitionReader 的作用是读取 Spring 的配置文件的内容,并将其转换成 Ioc 容器内部的数据结构:BeanDefinition。

ApplicationContext体系

这个就是大名鼎鼎的 Spring 容器,它叫做应用上下文,与我们应用息息相关,她继承 BeanFactory,所以它是 BeanFactory 的扩展升级版,如果BeanFactory 是屌丝的话,那么 ApplicationContext 则是名副其实的高富帅。由于 ApplicationContext 的结构就决定了它与 BeanFactory 的不同,其主要区别有:

  1. 继承 MessageSource,提供国际化的标准访问策略。
  2. 继承 ApplicationEventPublisher ,提供强大的事件机制。
  3. 扩展 ResourceLoader,可以用来加载多个 Resource,可以灵活访问不同的资源。
  4. 对 Web 应用的支持。

下图来源:https://blog.csdn.net/yujin753/article/details/47043143

上面五个体系可以说是 Spring IoC 中最核心的部分,后面博文也是针对这五个部分进行源码分析。其实 IoC 咋一看还是挺简单的,无非就是将配置文件(暂且认为是 xml 文件)进行解析(分析 xml 谁不会啊),然后放到一个 Map 里面就差不多了,初看有道理,其实要面临的问题还是有很多的,下面就劳烦各位看客跟着 LZ 博客来一步一步揭开 Spring IoC 的神秘面纱。

文章来自:https://blog.csdn.net/chenssy/article/details/82343456

【死磕 Spring】----- IOC 之深入理解 Spring IoC相关推荐

  1. 请简述什么是spring的ioc和di_理解Spring中的IoC和DI

    什么是IoC和DI IoC(Inversion of Control 控制反转):是一种面向对象编程中的一种设计原则,用来减低计算机代码之间的耦合度.其基本思想是:借助于"第三方" ...

  2. spring生命周期_理解Spring应用上下文生命周期

    Spring应用上下文启动准备阶段 `BeanFactory`创建阶段 `BeanFactory`准备阶段 `BeanFactory`后置处理阶段 `AnnotationConfigServletWe ...

  3. 【死磕 Spring】—– 死磕 Spring 精品合集

    Java面经 2019-03-05 09:00:40 原文:http://cmsblogs.com/?cat=206 [死磕 Spring]-– IOC 之深入理解 Spring IoC [死磕 Sp ...

  4. 彻底理解Spring IOC和DI

    目录 前言 1. 分享Iteye的开涛对Ioc的精彩讲解 1.1 IoC是什么 1.2 IoC能做什么 1.3 IoC和DI 2. 分享Bromon的blog上对IoC与DI浅显易懂的讲解 2.1 I ...

  5. 深入理解Spring IOC和AOP

    文章目录 1. 什么是 Spring 框架? 1.1Spring简介 1.2Spring的好处 1.3Spring体系结构 2.理解Spring IoC 2.1IoC简介 2.2IoC的好处 2.3依 ...

  6. 从面向对象设计思想出发理解Spring AOP编程

    都说AOP是OOP(面向对象)的继承与延续,我觉得理解AOP还是得从OOP出发,经历从暴露问题到解决问题的过程. 目录 一. 面向对象设计思想(OOP) (1)概述 1. POP编程 2. OOP的优 ...

  7. 对Spring loC DI的理解

    文章转自https://www.cnblogs.com/Mr-Rocker/p/7721824.html,仅供个人学习所用,好东西当然要多多学习啊(#^.^#) 学习过Spring框架的人一定都会听过 ...

  8. 死磕Java并发:深入分析synchronized的实现原理

    本文转载自公众号: Java技术驿站 记得刚刚开始学习Java的时候,一遇到多线程情况就是synchronized.对于当时的我们来说,synchronized是如此的神奇且强大.我们赋予它一个名字& ...

  9. Spring学习:一、Spring概述、Spring入门

    1 Spring概述 1.1 什么是Spring Rod Johnson(http://baike.baidu.com/item/Rod Johnson)在2002年编著的<Expert one ...

  10. preg_match 参数获取两个_「死磕 Spring」—– IOC 之 获取 Document 对象

    原文出自:http://cmsblogs.com作者:chenssy 在 XmlBeanDefinitionReader.doLoadDocument() 方法中做了两件事情,一是调用 getVali ...

最新文章

  1. oracle安装过程掉电,oracle数据库掉电恢复
  2. css Table布局:基于display:table的CSS布局
  3. Java 8的6个问题
  4. 数据库之事务及事务的 ACID 性质
  5. [EffectiveC++]item22:Declare data members private
  6. 常用的位操作:置位、清零与测试
  7. linux 完全卸载软件方法
  8. cacti 监控平台部署心得
  9. 为什么C#有委托,而Java没有?
  10. mysql 不等于查询优化_MySQL查询性能优化
  11. ant 使用java 运行类_用ANT构建java可执行程序
  12. video autoplay失效
  13. 来吧,一文彻底搞懂Java中最特殊的存在——null
  14. word中如何去掉文档右侧带格式的批注框
  15. 阿里云国际站:阿里云架构变革背后:刺破宁静 激活新增长
  16. Ultra-Fast Mathematician
  17. Go--Redis快速入门指南
  18. 2012网赛成都赛区
  19. QA | 关于信号发生器的扫频功能,您了解多少?
  20. Jmeter安装教程(windows)

热门文章

  1. “窗体”工具栏控件和“控件工具箱”控件基础
  2. JS测试显示屏分辨率以及屏幕尺寸
  3. 生态愿景与险企数字化进度——保险科技生态建设
  4. 利用Arthas进行简单的故障注入
  5. Java实现经纬度格式转化
  6. JavaScript的BOM(浏览器对象模型)部分知识点与DOM(文档对象模型)
  7. mysql ibatis count_[mysql] mysql-myibatis-整理
  8. from scipy.misc import comb ImportError: cannot import name ‘comb‘
  9. [IMX6Q]fastboot下载u-boot.bin失败提示太大原因
  10. 列车停站方案_城市轨道交通列车停站方案