前文已经介绍了Spring Bean的生命周期,在这个周期内有一个重要的概念就是: IOC容器java
你们也知道IOC是Sping 的重要核心之一,那么如何理解它呢,它又是产生什么做用呢?本文就IOC原理进行简要阐述。缓存
IoC 全称为 Inversion of Control
,翻译为 “控制反转”,它还有一个别名为 DI(Dependency Injection
),即依赖注入。安全
DI—Dependency Injection,即“依赖注入”:组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。ide
依赖注入的目的并不是为软件系统带来更多功能,而是为了提高组件重用的频率,并为系统搭建一个灵活、可扩展的平台。性能
经过依赖注入机制,咱们只须要经过简单的配置,而无需任何代码就可指定目标须要的资源,完成自身的业务逻辑,而不须要关心具体的资源来自何处,由谁实现。this
如何理解“控制反转”好呢?理解好它的关键在于咱们须要回答以下四个问题:spa
IoC和DI由什么关系呢?其实它们是同一个概念的不一样角度描述,因为控制反转概念比较含糊(可能只是理解为容器控制对象这一个层面,很难让人想到谁来维护对象关系),因此2004年大师级人物Martin Fowler又给出了一个新的名字:“依赖注入”,相对IoC 而言,“依赖注入”明确描述了“被注入对象依赖IoC容器配置依赖对象”。翻译
以年轻小伙子找女友为例子来讲明IOC的做用:code
/** * 年轻小伙子 */ 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() ,也就是本身去建立一个女友对象。这个过程复杂而又繁琐,并且咱们必需要面对每一个环节,同时使用完成以后咱们还要负责销毁它。对象
小伙子本身不用去找女友,反过来找IOC,IOC就至关于一个婚介公司,它管理着不少男男女女的资料,小伙子直接跟婚介公司提出需求,婚介公司则会根据需求提供一个妹子给咱们,咱们只须要负责使用它就好了。
因此,简单点说,IoC 的理念就是让别人为你服务
能够理解为: IOC主动把妹子注入给想使用它的小伙子。 (调用的时候使用Autowied ,这个对象就是前文说的bean, 经过注册进入IOC容器,被实例化以后再进入IOC容器的bean缓存池,就能够供程序调用了,这就和bean的生命周期连了起来。)
经过IOC的注册机制能够保证对象的安全性和合规性;
实例化对象只须要实例化一次,便可进入IOC容器的bean缓存池,下降了对象的建立开销,提升了程序的性能(有点相似单例);
应用程序调用对象从bean缓存池获取,这样是秒获取对象,提升了调用对象的速度。
如今来回答上面那四个问题,答案就显得很是明显了:
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 方式注入会显得比较宽松灵活些,它能够在任什么时候候进行注入(固然是在使用依赖对象以前),这就比如你能够先把本身想要的妹子想好了,而后再跟婚介公司打招呼,你能够要林志玲款式的,赵丽颖款式的,随意性较强。
通常程序中会使用这种方法进行实例化。
接口方式注入
接口方式注入显得比较霸道,由于它须要被依赖的对象实现没必要要的接口,带有侵入性。通常都不推荐这种方式。
A对象须要使用合做对象B来共同完成一件事,A要使用B,那么A就对B产生了依赖,也就是A和B之间存在一种耦合关系,而且是紧密耦合在一块儿。
而使用了Spring以后就不同了,建立合做对象B的工做是由Spring来作的,Spring建立好B对象,而后存储到一个容器里面,当A对象须要使用B对象时,Spring就从存放对象的那个容器里面取出A要使用的那个B对象,而后交给A对象使用,至于Spring是如何建立那个对象,以及何时建立好对象的,A对象不须要关心这些细节问题(你是何时生的,怎么生出来的我可不关心,能帮我干活就行),A获得Spring给咱们的对象以后,两我的一块儿协做完成要完成的工做便可。
因此控制反转IoC(Inversion of Control)是说建立对象的控制权进行转移,之前建立对象的主动权和建立时机是由本身把控的,而如今这种权力转移到第三方,好比转移交给了IoC容器,它就是一个专门用来建立对象的工厂,你要什么对象,它就给你什么对象,有了 IoC容器,依赖关系就变了,原先的依赖关系就没了,它们都依赖IoC容器了,经过IoC容器来创建它们之间的关系。