您好,登錄后才能下訂單哦!
這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)碛嘘P(guān)Spring的IOC原理是什么,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
我們都知道,在采用面向?qū)ο蠓椒ㄔO(shè)計(jì)的軟件系統(tǒng)中,它的底層實(shí)現(xiàn)都是由N個(gè)對(duì)象組成的,所有的對(duì)象通過彼此的合作,最終實(shí)現(xiàn)系統(tǒng)的業(yè)務(wù)邏輯。
圖1:軟件系統(tǒng)中耦合的對(duì)象
如果我們打開機(jī)械式手表的后蓋,就會(huì)看到與上面類似的情形,各個(gè)齒輪分別帶動(dòng)時(shí)針、分針和秒針順時(shí)針旋轉(zhuǎn),從而在表盤上產(chǎn)生正確的時(shí)間。
圖1中描述的就是這樣的一個(gè)齒輪組,它擁有多個(gè)獨(dú)立的齒輪,這些齒輪相互嚙合在一起,協(xié)同工作,共同完成某項(xiàng)任務(wù)。我們可以看到,在這樣的齒輪組中,如果有一個(gè)齒輪出了問題,就可能會(huì)影響到整個(gè)齒輪組的正常運(yùn)轉(zhuǎn)。
齒輪組中齒輪之間的嚙合關(guān)系,與軟件系統(tǒng)中對(duì)象之間的耦合關(guān)系非常相似。對(duì)象之間的耦合關(guān)系是無法避免的,也是必要的,這是協(xié)同工作的基礎(chǔ)?,F(xiàn)在,伴隨著工業(yè)級(jí)應(yīng)用的規(guī)模越來越龐大,對(duì)象之間的依賴關(guān)系也越來越復(fù)雜,經(jīng)常會(huì)出現(xiàn)對(duì)象之間的多重依賴性關(guān)系,因此,架構(gòu)師和設(shè)計(jì)師對(duì)于系統(tǒng)的分析和設(shè)計(jì),將面臨更大的挑戰(zhàn)。對(duì)象之間耦合度過高的系統(tǒng),必然會(huì)出現(xiàn)牽一發(fā)而動(dòng)全身的情形。
圖2:對(duì)象之間復(fù)雜的依賴關(guān)系
耦合關(guān)系不僅會(huì)出現(xiàn)在對(duì)象與對(duì)象之間,也會(huì)出現(xiàn)在軟件系統(tǒng)的各模塊之間,以及軟件系統(tǒng)和硬件系統(tǒng)之間。如何降低系統(tǒng)之間、模塊之間和對(duì)象之間的耦合度,是軟件工程永遠(yuǎn)追求的目標(biāo)之一。為了解決對(duì)象之間的耦合度過高的問題,軟件專家Michael Mattson提出了IOC理論,用來實(shí)現(xiàn)對(duì)象之間的“解耦”,目前這個(gè)理論已經(jīng)被成功地應(yīng)用到實(shí)踐當(dāng)中,很多的J2EE項(xiàng)目均采用了IOC框架產(chǎn)品Spring。
IOC是Inversion of Control的縮寫,多數(shù)書籍翻譯成“控制反轉(zhuǎn)”,還有些書籍翻譯成為“控制反向”或者“控制倒置”。
1996年,Michael Mattson在一篇有關(guān)探討面向?qū)ο罂蚣艿奈恼轮校紫忍岢隽薎OC 這個(gè)概念。對(duì)于面向?qū)ο笤O(shè)計(jì)及編程的基本思想,前面我們已經(jīng)講了很多了,不再贅述,簡(jiǎn)單來說就是把復(fù)雜系統(tǒng)分解成相互合作的對(duì)象,這些對(duì)象類通過封裝以后,內(nèi)部實(shí)現(xiàn)對(duì)外部是透明的,從而降低了解決問題的復(fù)雜度,而且可以靈活地被重用和擴(kuò)展。IOC理論提出的觀點(diǎn)大體是這樣的:借助于“第三方”實(shí)現(xiàn)具有依賴關(guān)系的對(duì)象之間的解耦,如下圖:
圖3:IOC解耦過程
大家看到了吧,由于引進(jìn)了中間位置的“第三方”,也就是IOC容器,使得A、B、C、D這4個(gè)對(duì)象沒有了耦合關(guān)系,齒輪之間的傳動(dòng)全部依靠“第三方”了,全部對(duì)象的控制權(quán)全部上繳給“第三方”IOC容器,所以,IOC容器成了整個(gè)系統(tǒng)的關(guān)鍵核心,它起到了一種類似“粘合劑”的作用,把系統(tǒng)中的所有對(duì)象粘合在一起發(fā)揮作用,如果沒有這個(gè)“粘合劑”,對(duì)象與對(duì)象之間會(huì)彼此失去聯(lián)系,這就是有人把IOC容器比喻成“粘合劑”的由來。
我們?cè)賮碜鰝€(gè)試驗(yàn):把上圖中間的IOC容器拿掉,然后再來看看這套系統(tǒng):
圖4:拿掉IoC容器后的系統(tǒng)
我們現(xiàn)在看到的畫面,就是我們要實(shí)現(xiàn)整個(gè)系統(tǒng)所需要完成的全部?jī)?nèi)容。這時(shí)候,A、B、C、D這4個(gè)對(duì)象之間已經(jīng)沒有了耦合關(guān)系,彼此毫無聯(lián)系,這樣的話,當(dāng)你在實(shí)現(xiàn)A的時(shí)候,根本無須再去考慮B、C和D了,對(duì)象之間的依賴關(guān)系已經(jīng)降低到了最低程度。所以,如果真能實(shí)現(xiàn)IOC容器,對(duì)于系統(tǒng)開發(fā)而言,這將是一件多么美好的事情,參與開發(fā)的每一成員只要實(shí)現(xiàn)自己的類就可以了,跟別人沒有任何關(guān)系!
我們?cè)賮砜纯?,控制反轉(zhuǎn)(IOC)到底為什么要起這么個(gè)名字?我們來對(duì)比一下:
軟件系統(tǒng)在沒有引入IOC容器之前,如圖1所示,對(duì)象A依賴于對(duì)象B,那么對(duì)象A在初始化或者運(yùn)行到某一點(diǎn)的時(shí)候,自己必須主動(dòng)去創(chuàng)建對(duì)象B或者使用已經(jīng)創(chuàng)建的對(duì)象B。無論是創(chuàng)建還是使用對(duì)象B,控制權(quán)都在自己手上。
軟件系統(tǒng)在引入IOC容器之后,這種情形就完全改變了,如圖3所示,由于IOC容器的加入,對(duì)象A與對(duì)象B之間失去了直接聯(lián)系,所以,當(dāng)對(duì)象A運(yùn)行到需要對(duì)象B的時(shí)候,IOC容器會(huì)主動(dòng)創(chuàng)建一個(gè)對(duì)象B注入到對(duì)象A需要的地方。
通過前后的對(duì)比,我們不難看出來:對(duì)象A獲得依賴對(duì)象B的過程,由主動(dòng)行為變?yōu)榱吮粍?dòng)行為,控制權(quán)顛倒過來了,這就是“控制反轉(zhuǎn)”這個(gè)名稱的由來。
2004年,Martin Fowler探討了同一個(gè)問題,既然IOC是控制反轉(zhuǎn),那么到底是“哪些方面的控制被反轉(zhuǎn)了呢?”,經(jīng)過詳細(xì)地分析和論證后,他得出了答案:“獲得依賴對(duì)象的過程被反轉(zhuǎn)了”。控制被反轉(zhuǎn)之后,獲得依賴對(duì)象的過程由自身管理變?yōu)榱擞蒊OC容器主動(dòng)注入。于是,他給“控制反轉(zhuǎn)”取了一個(gè)更合適的名字叫做“依賴注入(Dependency Injection)”。他的這個(gè)答案,實(shí)際上給出了實(shí)現(xiàn)IOC的方法:注入。所謂依賴注入,就是由IOC容器在運(yùn)行期間,動(dòng)態(tài)地將某種依賴關(guān)系注入到對(duì)象之中。
所以,依賴注入(DI)和控制反轉(zhuǎn)(IOC)是從不同的角度的描述的同一件事情,就是指通過引入IOC容器,利用依賴關(guān)系注入的方式,實(shí)現(xiàn)對(duì)象之間的解耦。
我們舉一個(gè)生活中的例子,來幫助理解依賴注入的過程。大家對(duì)USB接口和USB設(shè)備應(yīng)該都很熟悉吧,USB為我們使用電腦提供了很大的方便,現(xiàn)在有很多的外部設(shè)備都支持USB接口。
圖5:USB接口和USB設(shè)備
現(xiàn)在,我們利用電腦主機(jī)和USB接口來實(shí)現(xiàn)一個(gè)任務(wù):從外部USB設(shè)備讀取一個(gè)文件。
電腦主機(jī)讀取文件的時(shí)候,它一點(diǎn)也不會(huì)關(guān)心USB接口上連接的是什么外部設(shè)備,而且它確實(shí)也無須知道。它的任務(wù)就是讀取USB接口,掛接的外部設(shè)備只要符合USB接口標(biāo)準(zhǔn)即可。所以,如果我給電腦主機(jī)連接上一個(gè)U盤,那么主機(jī)就從U盤上讀取文件;如果我給電腦主機(jī)連接上一個(gè)外置硬盤,那么電腦主機(jī)就從外置硬盤上讀取文件。掛接外部設(shè)備的權(quán)力由我作主,即控制權(quán)歸我,至于USB接口掛接的是什么設(shè)備,電腦主機(jī)是決定不了,它只能被動(dòng)的接受。電腦主機(jī)需要外部設(shè)備的時(shí)候,根本不用它告訴我,我就會(huì)主動(dòng)幫它掛上它想要的外部設(shè)備,你看我的服務(wù)是多么的到位。這就是我們生活中常見的一個(gè)依賴注入的例子。在這個(gè)過程中,我就起到了IOC容器的作用。
通過這個(gè)例子,依賴注入的思路已經(jīng)非常清楚:當(dāng)電腦主機(jī)讀取文件的時(shí)候,我就把它所要依賴的外部設(shè)備,幫他掛接上。整個(gè)外部設(shè)備注入的過程和一個(gè)被依賴的對(duì)象在系統(tǒng)運(yùn)行時(shí)被注入另外一個(gè)對(duì)象內(nèi)部的過程完全一樣。
我們把依賴注入應(yīng)用到軟件系統(tǒng)中,再來描述一下這個(gè)過程:
對(duì)象A依賴于對(duì)象B,當(dāng)對(duì)象 A需要用到對(duì)象B的時(shí)候,IOC容器就會(huì)立即創(chuàng)建一個(gè)對(duì)象B送給對(duì)象A。IOC容器就是一個(gè)對(duì)象制造工廠,你需要什么,它會(huì)給你送去,你直接使用就行了,而再也不用去關(guān)心你所用的東西是如何制成的,也不用關(guān)心最后是怎么被銷毀的,這一切全部由IOC容器包辦。
在傳統(tǒng)的實(shí)現(xiàn)中,由程序內(nèi)部代碼來控制組件之間的關(guān)系。我們經(jīng)常使用new關(guān)鍵字來實(shí)現(xiàn)兩個(gè)組件之間關(guān)系的組合,這種實(shí)現(xiàn)方式會(huì)造成組件之間耦合。IOC很好地解決了該問題,它將實(shí)現(xiàn)組件間關(guān)系從程序內(nèi)部提到外部容器,也就是說由容器在運(yùn)行期將組件間的某種依賴關(guān)系動(dòng)態(tài)注入組件中。
我們還是從USB的例子說起,使用USB外部設(shè)備比使用內(nèi)置硬盤,到底帶來什么好處?
第一、USB設(shè)備作為電腦主機(jī)的外部設(shè)備,在插入主機(jī)之前,與電腦主機(jī)沒有任何的關(guān)系,只有被我們連接在一起之后,兩者才發(fā)生聯(lián)系,具有相關(guān)性。所以,無論兩者中的任何一方出現(xiàn)什么的問題,都不會(huì)影響另一方的運(yùn)行。這種特性體現(xiàn)在軟件工程中,就是可維護(hù)性比較好,非常便于進(jìn)行單元測(cè)試,便于調(diào)試程序和診斷故障。代碼中的每一個(gè)Class都可以單獨(dú)測(cè)試,彼此之間互不影響,只要保證自身的功能無誤即可,這就是組件之間低耦合或者無耦合帶來的好處。
第二、USB設(shè)備和電腦主機(jī)的之間無關(guān)性,還帶來了另外一個(gè)好處,生產(chǎn)USB設(shè)備的廠商和生產(chǎn)電腦主機(jī)的廠商完全可以是互不相干的人,各干各事,他們之間唯一需要遵守的就是USB接口標(biāo)準(zhǔn)。這種特性體現(xiàn)在軟件開發(fā)過程中,好處可是太大了。每個(gè)開發(fā)團(tuán)隊(duì)的成員都只需要關(guān)心實(shí)現(xiàn)自身的業(yè)務(wù)邏輯,完全不用去關(guān)心其它的人工作進(jìn)展,因?yàn)槟愕娜蝿?wù)跟別人沒有任何關(guān)系,你的任務(wù)可以單獨(dú)測(cè)試,你的任務(wù)也不用依賴于別人的組件,再也不用扯不清責(zé)任了。所以,在一個(gè)大中型項(xiàng)目中,團(tuán)隊(duì)成員分工明確、責(zé)任明晰,很容易將一個(gè)大的任務(wù)劃分為細(xì)小的任務(wù),開發(fā)效率和產(chǎn)品質(zhì)量必將得到大幅度的提高。
第三、同一個(gè)USB外部設(shè)備可以插接到任何支持USB的設(shè)備,可以插接到電腦主機(jī),也可以插接到DV機(jī),USB外部設(shè)備可以被反復(fù)利用。在軟件工程中,這種特性就是可復(fù)用性好,我們可以把具有普遍性的常用組件獨(dú)立出來,反復(fù)利用到項(xiàng)目中的其它部分,或者是其它項(xiàng)目,當(dāng)然這也是面向?qū)ο蟮幕咎卣鳌o@然,IOC不僅更好地貫徹了這個(gè)原則,提高了模塊的可復(fù)用性。符合接口標(biāo)準(zhǔn)的實(shí)現(xiàn),都可以插接到支持此標(biāo)準(zhǔn)的模塊中。
第四、同USB外部設(shè)備一樣,模塊具有熱插拔特性。IOC生成對(duì)象的方式轉(zhuǎn)為外置方式,也就是把對(duì)象生成放在配置文件里進(jìn)行定義,這樣,當(dāng)我們更換一個(gè)實(shí)現(xiàn)子類將會(huì)變得很簡(jiǎn)單,只要修改配置文件就可以了,完全具有熱插撥的特性。
以上幾點(diǎn)好處,難道還不足以打動(dòng)我們,讓我們?cè)陧?xiàng)目開發(fā)過程中使用IOC框架嗎?
IOC中最基本的技術(shù)就是“反射(Reflection)”編程,目前.Net C#、Java和PHP5等語(yǔ)言均支持,其中PHP5的技術(shù)書籍中,有時(shí)候也被翻譯成“映射”。有關(guān)反射的概念和用法,大家應(yīng)該都很清楚,通俗來講就是根據(jù)給出的類名(字符串方式)來動(dòng)態(tài)地生成對(duì)象。這種編程方式可以讓對(duì)象在生成時(shí)才決定到底是哪一種對(duì)象。反射的應(yīng)用是很廣泛的,很多的成熟的框架,比如象Java中的Hibernate、Spring框架,.Net中 NHibernate、Spring.Net框架都是把“反射”做為最基本的技術(shù)手段。
反射技術(shù)其實(shí)很早就出現(xiàn)了,但一直被忽略,沒有被進(jìn)一步的利用。當(dāng)時(shí)的反射編程方式相對(duì)于正常的對(duì)象生成方式要慢至少得10倍?,F(xiàn)在的反射技術(shù)經(jīng)過改良優(yōu)化,已經(jīng)非常成熟,反射方式生成對(duì)象和通常對(duì)象生成方式,速度已經(jīng)相差不大了,大約為1-2倍的差距。
我們可以把IOC容器的工作模式看做是工廠模式的升華,可以把IOC容器看作是一個(gè)工廠,這個(gè)工廠里要生產(chǎn)的對(duì)象都在配置文件中給出定義,然后利用編程語(yǔ)言的的反射編程,根據(jù)配置文件中給出的類名生成相應(yīng)的對(duì)象。從實(shí)現(xiàn)來看,IOC是把以前在工廠方法里寫死的對(duì)象生成代碼,改變?yōu)橛膳渲梦募矶x,也就是把工廠和對(duì)象生成這兩者獨(dú)立分隔開來,目的就是提高靈活性和可維護(hù)性。
Sun ONE技術(shù)體系下的IOC容器有:輕量級(jí)的有Spring、Guice、Pico Container、Avalon、HiveMind;重量級(jí)的有EJB;不輕不重的有JBoss,Jdon等等。Spring框架作為Java開發(fā)中SSH(Struts、Spring、Hibernate)三劍客之一,大中小項(xiàng)目中都有使用,非常成熟,應(yīng)用廣泛,EJB在關(guān)鍵性的工業(yè)級(jí)項(xiàng)目中也被使用,比如某些電信業(yè)務(wù)。
.Net技術(shù)體系下的IOC容器有:Spring.Net、Castle等等。Spring.Net是從Java的Spring移植過來的IOC容器,Castle的IOC容器就是Windsor部分。它們均是輕量級(jí)的框架,比較成熟,其中Spring.Net已經(jīng)被逐漸應(yīng)用于各種項(xiàng)目中。
使用IOC框架產(chǎn)品能夠給我們的開發(fā)過程帶來很大的好處,但是也要充分認(rèn)識(shí)引入IOC框架的缺點(diǎn),做到心中有數(shù),杜絕濫用框架。
第一、軟件系統(tǒng)中由于引入了第三方IOC容器,生成對(duì)象的步驟變得有些復(fù)雜,本來是兩者之間的事情,又憑空多出一道手續(xù),所以,我們?cè)趧傞_始使用IOC框架的時(shí)候,會(huì)感覺系統(tǒng)變得不太直觀。所以,引入了一個(gè)全新的框架,就會(huì)增加團(tuán)隊(duì)成員學(xué)習(xí)和認(rèn)識(shí)的培訓(xùn)成本,并且在以后的運(yùn)行維護(hù)中,還得讓新加入者具備同樣的知識(shí)體系。
第二、由于IOC容器生成對(duì)象是通過反射方式,在運(yùn)行效率上有一定的損耗。如果你要追求運(yùn)行效率的話,就必須對(duì)此進(jìn)行權(quán)衡。
第三、具體到IOC框架產(chǎn)品(比如:Spring)來講,需要進(jìn)行大量的配制工作,比較繁瑣,對(duì)于一些小的項(xiàng)目而言,客觀上也可能加大一些工作成本。
第四、IOC框架產(chǎn)品本身的成熟度需要進(jìn)行評(píng)估,如果引入一個(gè)不成熟的IOC框架產(chǎn)品,那么會(huì)影響到整個(gè)項(xiàng)目,所以這也是一個(gè)隱性的風(fēng)險(xiǎn)。
上述就是小編為大家分享的Spring的IOC原理是什么了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。