Spring中的IOC深度解讀
spring容器
spring容器的概念,容器這個(gè)名字起的相當(dāng)好,容器可以放很多東西,我們的程序啟動(dòng)的時(shí)候會(huì)創(chuàng)建spring容器,會(huì)給spring容器一個(gè)清單,清單中列出了需要?jiǎng)?chuàng)建的對(duì)象以及對(duì)象依賴關(guān)系,spring容器會(huì)創(chuàng)建和組裝好清單中的對(duì)象,然后將這些對(duì)象存放在spring容器中,當(dāng)程序中需要使用的時(shí)候,可以到容器中查找獲取,然后直接使用。
IOC:控制反轉(zhuǎn)
使用者之前使用B對(duì)象的時(shí)候都需要自己去創(chuàng)建和組裝,而現(xiàn)在這些創(chuàng)建和組裝都交給spring容器去給完成了,使用者只需要去spring容器中查找需要使用的對(duì)象就可以了;這個(gè)過(guò)程中B對(duì)象的創(chuàng)建和組裝過(guò)程被反轉(zhuǎn)了,之前是使用者自己主動(dòng)去控制的,現(xiàn)在交給spring容器去創(chuàng)建和組裝了,對(duì)象的構(gòu)建過(guò)程被反轉(zhuǎn)了,所以叫做控制反轉(zhuǎn);IOC是是面相對(duì)象編程中的一種設(shè)計(jì)原則,主要是為了降低系統(tǒng)代碼的耦合度,讓系統(tǒng)利于維護(hù)和擴(kuò)展。
DI:依賴注入
依賴注入是spring容器中創(chuàng)建對(duì)象時(shí)給其設(shè)置依賴對(duì)象的方式,比如給spring一個(gè)清單,清單中列出了需要?jiǎng)?chuàng)建B對(duì)象以及其他的一些對(duì)象(可能包含了B類型中需要依賴對(duì)象),此時(shí)spring在創(chuàng)建B對(duì)象的時(shí)候,會(huì)看B對(duì)象需要依賴于哪些對(duì)象,然后去查找一下清單中有沒(méi)有包含這些被依賴的對(duì)象,如果有就去將其創(chuàng)建好,然后將其傳遞給B對(duì)象;可能B需要依賴于很多對(duì)象,B創(chuàng)建之前完全不需要知道其他對(duì)象是否存在或者其他對(duì)象在哪里以及被他們是如何創(chuàng)建,而spring容器會(huì)將B依賴對(duì)象主動(dòng)創(chuàng)建好并將其注入到B中去,比如spring容器創(chuàng)建B的時(shí)候,發(fā)現(xiàn)B需要依賴于A,那么spring容器在清單中找到A的定義并將其創(chuàng)建好之后,注入到B對(duì)象中。
spring中依賴注入主要分為手動(dòng)注入和自動(dòng)注入:
手動(dòng)注入需要由程序員自己配置、描述好依賴關(guān)系,來(lái)實(shí)現(xiàn)自動(dòng)注入(但是實(shí)際開(kāi)發(fā)中手動(dòng)裝配的場(chǎng)景比較少,比如在缺少源碼的情況下可能會(huì)使用這種手動(dòng)裝配情況)。
自動(dòng)注入采用約定大于配置的方式來(lái)實(shí)現(xiàn)的,程序和spring容器之間約定好,遵守某一種都認(rèn)同的規(guī)則,來(lái)實(shí)現(xiàn)自動(dòng)注入。
DI:依賴注入的實(shí)現(xiàn)方式
分別是基于構(gòu)造方法的依賴注入和基于setter(setXxxx(…))的依賴注入。
不管是手動(dòng)裝配還是自動(dòng)裝配都是基于這兩種方式或者變體方式來(lái)的;但是這里一定要回答到主要和變體兩個(gè)名詞,因?yàn)橛械淖⑷敕绞骄筒皇沁@兩種,而是這兩種其中一種的變體方式;比如在一個(gè)類的屬性上面加@Autowired,這種方式注入屬性的方式就是利用了java的反射知識(shí),field.set(value,targetObject);關(guān)于這個(gè)我在后面的文章中對(duì)spring源碼解析的時(shí)候會(huì)說(shuō)明@Autowired的原理;所以@Autowired這種注入的方式是setter注入方式的一種變體
DI:依賴注入的自動(dòng)裝配模型
依賴注入是一個(gè)過(guò)程,主要通過(guò)setter或構(gòu)造方法以及一些變體的方式完成把對(duì)象依賴、或者填充上的這個(gè)過(guò)程叫做依賴注入,不管手動(dòng)裝配還是自動(dòng)裝配都有這個(gè)過(guò)程;
手動(dòng)裝配通過(guò)ref標(biāo)簽來(lái)指定依賴關(guān)系,而自動(dòng)裝配沒(méi)有顯示的指定依賴關(guān)系,所以需要通過(guò)一些規(guī)則,來(lái)從容器中查找到符合條件的bean進(jìn)行自動(dòng)裝配的工作,而自動(dòng)裝配模型就是完成自動(dòng)裝配依賴的手段體現(xiàn)。
每一種模型都使用了不同的技術(shù)去查找和填充bean;而從spring官網(wǎng)上面可以看到spring只提出了4中自動(dòng)裝配模型(嚴(yán)格意義上是三種、因?yàn)榈谝环N是no,表示不使用自動(dòng)裝配、使用),這四個(gè)模型分別用一個(gè)整形來(lái)表示,存在spring的beanDefinition當(dāng)中,任何一個(gè)類默認(rèn)是no這個(gè)裝配模型
我們可以在AutowireCapableBeanFactory類中看下這幾種自動(dòng)裝配模型對(duì)應(yīng)的整形分別是多少
public interface AutowireCapableBeanFactory extends BeanFactory { int AUTOWIRE_NO = 0; int AUTOWIRE_BY_NAME = 1; int AUTOWIRE_BY_TYPE = 2; int AUTOWIRE_CONSTRUCTOR = 3; @Deprecated int AUTOWIRE_AUTODETECT = 4; }
@Autowired就是根據(jù)byType來(lái)進(jìn)行自動(dòng)裝配
我們先拋出@Autowired的查找邏輯的結(jié)論:
首先spring根據(jù)類型去容器中找,找到了直接注入。如果根據(jù)類型找到了多個(gè),那么spring不會(huì)立馬異常,而是根據(jù)名字再去找,如果根據(jù)名字找到一個(gè)合理的則注入這個(gè)合理的。
如果沒(méi)有找到,再根據(jù)名字去找,找到了則注入,沒(méi)有找到則報(bào)異常。
我們?cè)賮?lái)用代碼來(lái)驗(yàn)證下
定義一個(gè)空接口I,XY類分別實(shí)現(xiàn)I接口,Z類中注入I
public interface I { }
package com.yj.service.impl; import org.springframework.stereotype.Component; import com.yj.service.I; @Component("ix") public class X implements I{ }
package com.yj.service.impl; import org.springframework.stereotype.Component; import com.yj.service.I; @Component("iy") public class Y implements I{ }
@Component public class Z { @Autowired private I ix; public I getIx() { return ix; } public void setIx(I ix) { this.ix = ix; } }
掃描配置類
package com.yj.conf; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @Configuration @ComponentScan("com.yj") public class AppConfig { }
MyBeanFactoryProcessor
package com.yj.conf; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.stereotype.Component; @Component public class MyBeanFactoryProcessor implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition)beanFactory.getBeanDefinition("z"); //beanDefinition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE); System.out.println("beanDefinition.getAutowireMode():"+beanDefinition.getAutowireMode()); } }
首先,我們可以觀察到被@Autowired注解的z類的getAutowireMode值為0,不是2。而且我們?nèi)绻謩?dòng)將z類的AutowireMode設(shè)置為ByType,只是根據(jù)類型來(lái)查找的話,會(huì)查出XY兩個(gè)bean,程序會(huì)報(bào)錯(cuò)的。
但是采用@Autowired默認(rèn)的注入方式,是不會(huì)報(bào)錯(cuò)的,也就是說(shuō)@Autowired的查找邏輯并不能簡(jiǎn)單的認(rèn)為等價(jià)于ByType,@Autowired首先根據(jù)類型然后再根據(jù)名字去查找,完成bean注入的過(guò)程。
到此這篇關(guān)于Spring中的IOC深度解讀的文章就介紹到這了,更多相關(guān)IOC深度解讀內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
spring mvc4中相關(guān)注解的詳細(xì)講解教程
這篇文章主要給大家介紹了關(guān)于spring mvc4中相關(guān)注解的相關(guān)資料,其中詳細(xì)介紹了關(guān)于@Controller、@RequestMapping、@RathVariable、@RequestParam及@RequestBody等等注解的相關(guān)內(nèi)容,需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-06-06java創(chuàng)建線程池的7種實(shí)現(xiàn)方法
在Java中線程池是一種管理線程的機(jī)制,它可以創(chuàng)建一組線程并重復(fù)使用它們,避免了創(chuàng)建和銷毀線程的開(kāi)銷,這篇文章主要給大家介紹了關(guān)于java創(chuàng)建線程池的7種實(shí)現(xiàn)方法,需要的朋友可以參考下2023-10-10Spring Boot 2.0快速構(gòu)建服務(wù)組件全步驟
這篇文章主要給大家介紹了關(guān)于Spring Boot 2.0快速構(gòu)建服務(wù)組件的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Spring Boot 2.0具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04對(duì)比Java中的Comparable排序接口和Comparator比較器接口
Comparable和Comparator接口都可用作普通意義上對(duì)象間的比大小,但兩個(gè)接口在實(shí)例化方面的用法不盡相同,接下來(lái)我們就來(lái)詳細(xì)對(duì)比Java中的Comparable排序接口和Comparator比較器接口2016-05-05Jmeter生成UUID作為唯一標(biāo)識(shí)符過(guò)程圖解
這篇文章主要介紹了Jmeter生成UUID作為唯一標(biāo)識(shí)符過(guò)程圖解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08java讀寫excel文件實(shí)現(xiàn)POI解析Excel的方法
在日常工作中,我們常常會(huì)進(jìn)行Excel文件讀寫操作,這篇文章主要介紹了java讀寫excel文件實(shí)現(xiàn)POI解析Excel的方法,實(shí)例分析了java讀寫excel的技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2018-10-10Springboot使用redis實(shí)現(xiàn)接口Api限流的實(shí)例
本文介紹的內(nèi)容如題,就是利用redis實(shí)現(xiàn)接口的限流(某時(shí)間范圍內(nèi),最大的訪問(wèn)次數(shù)),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-07-07Java httpcomponents發(fā)送get post請(qǐng)求代碼實(shí)例
這篇文章主要介紹了Java httpcomponents發(fā)送get post請(qǐng)求代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09SpringBoot使用Editor.md構(gòu)建Markdown富文本編輯器示例
這篇文章主要介紹了SpringBoot使用Editor.md構(gòu)建Markdown富文本編輯器示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-03-03