在一开始学习 Spring 的时候,咱们就接触 IoC 了,做为 Spring 第一个最核心的概念,咱们在解读它源码以前必定须要对其有深刻的认识,本篇为【死磕 Spring】系列博客的第一篇博文,主要介绍 IoC 基本概念和各个组件。html
IoC 全称为 Inversion of Control
,翻译为 “控制反转”,它还有一个别名为 DI(Dependency Injection
),即依赖注入。java
如何理解“控制反转”好呢?理解好它的关键在于咱们须要回答以下四个问题:spring
在回答这四个问题以前,咱们先看 IOC 的定义:微信
所谓 IOC ,就是由 Spring IOC 容器来负责对象的生命周期和对象之间的关系数据结构
上面这句话是整个 IoC 理论的核心。如何来理解这句话?咱们引用一个例子来走阐述(看完该例子上面四个问题也就不是问题了)。ide
已找女友为例(对于程序猿来讲这个值得探究的问题)。通常状况下咱们是如何来找女友的呢?首先咱们须要根据本身的需求(漂亮、身材好、性格好)找一个妹子,而后处处打听她的兴趣爱好、微信、电话号码,而后各类投其所好送其所要,最后追到手。以下:源码分析
/** * 年轻小伙子 */ 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); } }
这就是咱们一般作事的方式,若是咱们须要某个对象,通常都是采用这种直接建立的方式(new BeautifulGirl()
),这个过程复杂而又繁琐,并且咱们必需要面对每一个环节,同时使用完成以后咱们还要负责销毁它,在这种状况下咱们的对象与它所依赖的对象耦合在一块儿。学习
其实咱们须要思考一个问题?咱们每次用到本身依赖的对象真的须要本身去建立吗?咱们知道,咱们依赖对象其实并非依赖该对象自己,而是依赖它所提供的服务,只要在咱们须要它的时候,它可以及时提供服务便可,至于它是咱们主动去建立的仍是别人送给咱们的,其实并非那么重要。再说了,相比于本身千辛万苦去建立它还要管理、善后而言,直接有人送过来是否是显得更加好呢?this
这个给咱们送东西的“人” 就是 IoC,在上面的例子中,它就至关于一个婚介公司,做为一个婚介公司它管理着不少男男女女的资料,当咱们须要一个女友的时候,直接跟婚介公司提出咱们的需求,婚介公司则会根据咱们的需求提供一个妹子给咱们,咱们只须要负责谈恋爱,生猴子就好了。你看,这样是否是很简单明了。spa
诚然,做为婚介公司的 IoC 帮咱们省略了找女友的繁杂过程,将原来的主动寻找变成了如今的被动接受(符合咱们的要求),更加简洁轻便。你想啊,原来你还得鞍马先后,各类巴结,什么东西都须要本身去亲力亲为,如今好了,直接有人把现成的送过来,多么美妙的事情啊。因此,简单点说,IoC 的理念就是让别人为你服务,以下图(摘自Spring揭秘):
在没有引入 IoC 的时候,被注入的对象直接依赖于被依赖的对象,有了 IoC 后,二者及其余们的关系都是经过 Ioc Service Provider 来统一管理维护的。被注入的对象须要什么,直接跟 IoC Service Provider 打声招呼,后者就会把相应的被依赖对象注入到被注入的对象中,从而达到 IOC Service Provider 为被注入对象服务的目的。因此 IoC 就是这么简单!原来是须要什么东西本身去拿,如今是须要什么东西让别人(IOC Service Provider)送过来
如今在看上面那四个问题,答案就显得很是明显了:
妹子有了,可是如何拥有妹子呢?这也是一门学问。
因此,IOC Service Provider 为被注入对象提供被依赖对象也有以下几种方式:构造方法注入、stter方法注入、接口注入。
构造器注入
构造器注入,顾名思义就是被注入的对象经过在其构造方法中声明依赖对象的参数列表,让外部知道它须要哪些依赖对象。
YoungMan(BeautifulGirl beautifulGirl){ this.beautifulGirl = beautifulGirl; }
构造器注入方式比较直观,对象构造完毕后就能够直接使用,这就比如你出生你家里就给你指定了你媳妇。
setter 方法注入
对于 JavaBean 对象而言,咱们通常都是经过 getter 和 setter 方法来访问和设置对象的属性。因此,当前对象只须要为其所依赖的对象提供相对应的 setter 方法,就能够经过该方法将相应的依赖对象设置到被注入对象中。以下:
public class YoungMan { private BeautifulGirl beautifulGirl; public void setBeautifulGirl(BeautifulGirl beautifulGirl) { this.beautifulGirl = beautifulGirl; } }
相比于构造器注入,setter 方式注入会显得比较宽松灵活些,它能够在任什么时候候进行注入(固然是在使用依赖对象以前),这就比如你能够先把本身想要的妹子想好了,而后再跟婚介公司打招呼,你能够要林志玲款式的,赵丽颖款式的,甚至凤姐哪款的,随意性较强。
接口方式注入
接口方式注入显得比较霸道,由于它须要被依赖的对象实现没必要要的接口,带有侵入性。通常都不推荐这种方式。
关于 IOC 理论部分,笔者不在阐述,这里推荐几篇博客阅读:
先看下图(摘自: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 有三个直接子类 ListableBeanFactory
、HierarchicalBeanFactory
和 AutowireCapableBeanFactory
,DefaultListableBeanFactory
为最终默认实现,它实现了全部接口。
Beandefinition 体系
BeanDefinition 用来描述 Spring 中的 Bean 对象。
BeandefinitionReader体系
BeanDefinitionReader 的做用是读取 Spring 的配置文件的内容,并将其转换成 Ioc 容器内部的数据结构:BeanDefinition。
ApplicationContext体系
这个就是大名鼎鼎的 Spring 容器,它叫作应用上下文,与咱们应用息息相关,她继承 BeanFactory,因此它是 BeanFactory 的扩展升级版,若是BeanFactory 是屌丝的话,那么 ApplicationContext 则是名副其实的高富帅。因为 ApplicationContext 的结构就决定了它与 BeanFactory 的不一样,其主要区别有:
下图来源:https://blog.csdn.net/yujin753/article/details/47043143
上面五个体系能够说是 Spring IoC 中最核心的部分,后面博文也是针对这五个部分进行源码分析。其实 IoC 咋一看仍是挺简单的,无非就是将配置文件(暂且认为是 xml 文件)进行解析(分析 xml 谁不会啊),而后放到一个 Map 里面就差很少了,初看有道理,其实要面临的问题仍是有不少的,下面就劳烦各位看客跟着 LZ 博客来一步一步揭开 Spring IoC 的神秘面纱。
此系列博文为 LZ 学习、研究 Spring 机制和源码的学习笔记,会涉及参考别人的博文和书籍内容,若有雷同,纯属借鉴,固然 LZ 会标明参考来源。同时因为知识面和能力的问题,文章中不免会出现错误之处,若有,望各位大佬指出,不胜感激。
LZ 写此系列博客时,Spring 最新版本为 5.0.6.RELEASE ,因此此系列博客全部源码来源均为 5.0.6.RELEASE。