如何理解Spring IOC和DI

我先自己總結(jié)一下

IOC: 原來上層依賴下層,下層改變,上層也要大量的修改,不好.所以上層中拿著下層的對象,下層改變不影響上層.
DI: 上層持有下層對象,每次都要new,依賴傳遞下去,new一個上層對象,結(jié)果可能要依賴幾十個對象.太麻煩,所以spring幫我們做了控制反轉(zhuǎn),new你要的對象就行,其他的不用你管.它的實(shí)現(xiàn)就是:你要一個car,在創(chuàng)建car的時候發(fā)現(xiàn)car需要依賴框架frame,好,再創(chuàng)建一個frame,啊,創(chuàng)建frame需要底盤?行,給你創(chuàng)建個底盤,創(chuàng)建底盤時發(fā)現(xiàn)還需要輪胎,好再給你new 輪胎.new輪胎的時候,終于沒有依賴了.好,再反向的組裝起來,最后給你一個car.


好了,以下是原文
要了解控制反轉(zhuǎn)( Inversion of Control ), 我覺得有必要先了解軟件設(shè)計(jì)的一個重要思想:依賴倒置原則(Dependency Inversion Principle )


什么是依賴倒置原則茬暇?假設(shè)我們設(shè)計(jì)一輛汽車:先設(shè)計(jì)輪子椅您,然后根據(jù)輪子大小設(shè)計(jì)底盤膝昆,接著根據(jù)底盤設(shè)計(jì)車身,最后根據(jù)車身設(shè)計(jì)好整個汽車鸳谜。這里就出現(xiàn)了一個“依賴”關(guān)系:汽車依賴車身,車身依賴底盤,底盤依賴輪子并巍。

這樣的設(shè)計(jì)看起來沒問題,但是可維護(hù)性卻很低换途。假設(shè)設(shè)計(jì)完工之后懊渡,上司卻突然說根據(jù)市場需求的變動,要我們把車子的輪子設(shè)計(jì)都改大一碼军拟。這下我們就蛋疼了:因?yàn)槲覀兪歉鶕?jù)輪子的尺寸設(shè)計(jì)的底盤剃执,輪子的尺寸一改,底盤的設(shè)計(jì)就得修改懈息;同樣因?yàn)槲覀兪歉鶕?jù)底盤設(shè)計(jì)的車身肾档,那么車身也得改,同理汽車設(shè)計(jì)也得改——整個設(shè)計(jì)幾乎都得改辫继!
我們現(xiàn)在換一種思路阁最。我們先設(shè)計(jì)汽車的大概樣子,然后根據(jù)汽車的樣子來設(shè)計(jì)車身骇两,根據(jù)車身來設(shè)計(jì)底盤速种,最后根據(jù)底盤來設(shè)計(jì)輪子。這時候低千,依賴關(guān)系就倒置過來了:輪子依賴底盤配阵, 底盤依賴車身馏颂, 車身依賴汽車。

這時候棋傍,上司再說要改動輪子的設(shè)計(jì)救拉,我們就只需要改動輪子的設(shè)計(jì),而不需要動底盤瘫拣,車身亿絮,汽車的設(shè)計(jì)了。
這就是依賴倒置原則——把原本的高層建筑依賴底層建筑“倒置”過來麸拄,變成底層建筑依賴高層建筑派昧。高層建筑決定需要什么,底層去實(shí)現(xiàn)這樣的需求拢切,但是高層并不用管底層是怎么實(shí)現(xiàn)的蒂萎。這樣就不會出現(xiàn)前面的“牽一發(fā)動全身”的情況。

控制反轉(zhuǎn)(Inversion of Control) 就是依賴倒置原則的一種代碼設(shè)計(jì)的思路淮椰。具體采用的方法就是所謂的依賴注入(Dependency Injection)五慈。其實(shí)這些概念初次接觸都會感到云里霧里的。說穿了主穗,這幾種概念的關(guān)系大概如下:

為了理解這幾個概念泻拦,我們還是用上面汽車的例子。只不過這次換成代碼忽媒。我們先定義四個Class聪轿,車,車身猾浦,底盤陆错,輪胎。然后初始化這輛車金赦,最后跑這輛車音瓷。代碼結(jié)構(gòu)如下:

這樣,就相當(dāng)于上面第一個例子夹抗,上層建筑依賴下層建筑——每一個類的構(gòu)造函數(shù)都直接調(diào)用了底層代碼的構(gòu)造函數(shù)绳慎。假設(shè)我們需要改動一下輪胎(Tire)類,把它的尺寸變成動態(tài)的漠烧,而不是一直都是30杏愤。我們需要這樣改:

由于我們修改了輪胎的定義,為了讓整個程序正常運(yùn)行已脓,我們需要做以下改動:

由此我們可以看到珊楼,僅僅是為了修改輪胎的構(gòu)造函數(shù),這種設(shè)計(jì)卻需要修改整個上層所有類的構(gòu)造函數(shù)度液!在軟件工程中厕宗,這樣的設(shè)計(jì)幾乎是不可維護(hù)的——在實(shí)際工程項(xiàng)目中画舌,有的類可能會是幾千個類的底層,如果每次修改這個類已慢,我們都要修改所有以它作為依賴的類曲聂,那軟件的維護(hù)成本就太高了。
所以我們需要進(jìn)行控制反轉(zhuǎn)(IoC)佑惠,及上層控制下層朋腋,而不是下層控制著上層。我們用依賴注入(Dependency Injection)這種方式來實(shí)現(xiàn)控制反轉(zhuǎn)膜楷。所謂依賴注入旭咽,就是把底層類作為參數(shù)傳入上層類,實(shí)現(xiàn)上層類對下層類的“控制”把将。這里我們用構(gòu)造方法傳遞的依賴注入方式重新寫車類的定義:

這里我們再把輪胎尺寸變成動態(tài)的轻专,同樣為了讓整個系統(tǒng)順利運(yùn)行忆矛,我們需要做如下修改:

看到?jīng)]察蹲?這里我只需要修改輪胎類就行了,不用修改其他任何上層類催训。這顯然是更容易維護(hù)的代碼洽议。不僅如此,在實(shí)際的工程中漫拭,這種設(shè)計(jì)模式還有利于不同組的協(xié)同合作和單元測試:比如開發(fā)這四個類的分別是四個不同的組亚兄,那么只要定義好了接口,四個不同的組可以同時進(jìn)行開發(fā)而不相互受限制采驻;而對于單元測試审胚,如果我們要寫Car類的單元測試,就只需要Mock一下Framework類傳入Car就行了礼旅,而不用把Framework, Bottom, Tire全部new一遍再來構(gòu)造Car膳叨。
這里我們是采用的構(gòu)造函數(shù)傳入的方式進(jìn)行的依賴注入。其實(shí)還有另外兩種方法:Setter傳遞接口傳遞痘系。這里就不多講了菲嘴,核心思路都是一樣的,都是為了實(shí)現(xiàn)控制反轉(zhuǎn)汰翠。


看到這里你應(yīng)該能理解什么控制反轉(zhuǎn)和依賴注入了龄坪。那什么是控制反轉(zhuǎn)容器(IoC Container)呢?其實(shí)上面的例子中复唤,對車類進(jìn)行初始化的那段代碼發(fā)生的地方健田,就是控制反轉(zhuǎn)容器。

顯然你也應(yīng)該觀察到了佛纫,因?yàn)椴捎昧艘蕾囎⑷氤危诔跏蓟倪^程中就不可避免的會寫大量的new唱星。這里IoC容器就解決了這個問題。這個容器可以自動對你的代碼進(jìn)行初始化跟磨,你只需要維護(hù)一個Configuration(可以是xml可以是一段代碼)间聊,而不用每次初始化一輛車都要親手去寫那一大段初始化的代碼。這是引入IoC Container的第一個好處抵拘。
IoC Container的第二個好處是:我們在創(chuàng)建實(shí)例的時候不需要了解其中的細(xì)節(jié)哎榴。在上面的例子中,我們自己手動創(chuàng)建一個車instance時候僵蛛,是從底層往上層new的:

這個過程中尚蝌,我們需要了解整個Car/Framework/Bottom/Tire類構(gòu)造函數(shù)是怎么定義的,才能一步一步new/注入充尉。
而IoC Container在進(jìn)行這個工作的時候是反過來的飘言,它先從最上層開始往下找依賴關(guān)系,到達(dá)最底層之后再往上一步一步new(有點(diǎn)像深度優(yōu)先遍歷):

這里IoC Container可以直接隱藏具體的創(chuàng)建實(shí)例的細(xì)節(jié)驼侠,在我們來看它就像一個工廠:

我們就像是工廠的客戶姿鸿。我們只需要向工廠請求一個Car實(shí)例,然后它就給我們按照Config創(chuàng)建了一個Car實(shí)例倒源。我們完全不用管這個Car實(shí)例是怎么一步一步被創(chuàng)建出來苛预。
實(shí)際項(xiàng)目中,有的Service Class可能是十年前寫的笋熬,有幾百個類作為它的底層热某。假設(shè)我們新寫的一個API需要實(shí)例化這個Service,我們總不可能回頭去搞清楚這幾百個類的構(gòu)造函數(shù)吧胳螟?IoC Container的這個特性就很完美的解決了這類問題昔馋,大大增加了項(xiàng)目的可維護(hù)性且降低了開發(fā)難度。

這里只是很粗略的講了一下我自己對IoC和DI的理解糖耸。主要的目的是在于最大限度避免晦澀難懂的專業(yè)詞匯秘遏,用盡量簡潔,通俗蔬捷,直觀的例子來解釋這些概念垄提。如果讓大家能有一個類似“哦!原來就是這么個玩意嘛周拐!”的印象铡俐,我覺得就OK了。想要深入了解的話妥粟,可以上網(wǎng)查閱一些更權(quán)威的資料审丘。這里推薦一下 Dependency injection **Inversion of Control Containers and the Dependency Injection pattern** 這兩篇文章,講的很好很詳細(xì)勾给。

作者:Sevenvidia鏈接:https://www.zhihu.com/question/23277575/answer/169698662來源:知乎著作權(quán)歸作者所有滩报。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán)锅知,非商業(yè)轉(zhuǎn)載請注明出處。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末脓钾,一起剝皮案震驚了整個濱河市售睹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌可训,老刑警劉巖昌妹,帶你破解...
    沈念sama閱讀 211,817評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異握截,居然都是意外死亡飞崖,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評論 3 385
  • 文/潘曉璐 我一進(jìn)店門谨胞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來固歪,“玉大人,你說我怎么就攤上這事胯努±紊眩” “怎么了?”我有些...
    開封第一講書人閱讀 157,354評論 0 348
  • 文/不壞的土叔 我叫張陵康聂,是天一觀的道長贰健。 經(jīng)常有香客問我胞四,道長恬汁,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,498評論 1 284
  • 正文 為了忘掉前任辜伟,我火速辦了婚禮氓侧,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘导狡。我一直安慰自己约巷,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,600評論 6 386
  • 文/花漫 我一把揭開白布旱捧。 她就那樣靜靜地躺著独郎,像睡著了一般。 火紅的嫁衣襯著肌膚如雪枚赡。 梳的紋絲不亂的頭發(fā)上氓癌,一...
    開封第一講書人閱讀 49,829評論 1 290
  • 那天,我揣著相機(jī)與錄音贫橙,去河邊找鬼贪婉。 笑死,一個胖子當(dāng)著我的面吹牛卢肃,可吹牛的內(nèi)容都是我干的疲迂。 我是一名探鬼主播才顿,決...
    沈念sama閱讀 38,979評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼尤蒿!你這毒婦竟也來了郑气?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,722評論 0 266
  • 序言:老撾萬榮一對情侶失蹤腰池,失蹤者是張志新(化名)和其女友劉穎竣贪,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體巩螃,經(jīng)...
    沈念sama閱讀 44,189評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡演怎,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,519評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了避乏。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片爷耀。...
    茶點(diǎn)故事閱讀 38,654評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖拍皮,靈堂內(nèi)的尸體忽然破棺而出歹叮,到底是詐尸還是另有隱情,我是刑警寧澤铆帽,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布咆耿,位于F島的核電站,受9級特大地震影響爹橱,放射性物質(zhì)發(fā)生泄漏萨螺。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,940評論 3 313
  • 文/蒙蒙 一愧驱、第九天 我趴在偏房一處隱蔽的房頂上張望慰技。 院中可真熱鬧,春花似錦组砚、人聲如沸吻商。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽艾帐。三九已至,卻和暖如春盆偿,著一層夾襖步出監(jiān)牢的瞬間柒爸,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評論 1 266
  • 我被黑心中介騙來泰國打工陈肛, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留揍鸟,地道東北人。 一個月前我還...
    沈念sama閱讀 46,382評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像阳藻,于是被迫代替她去往敵國和親晰奖。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,543評論 2 349

推薦閱讀更多精彩內(nèi)容