依賴注入(Dependency Injection)


Spring的兩個核心內容為控制反轉(Ioc)和面向切面(AOP),依賴注入(DI)是控制反轉(Ioc)的一種方式。

依賴注入這個詞讓人望而生畏,現在已經演變成一項復雜的編程技巧 或設計模式理念。但事實證明,依賴注入並不像它聽上去那么復雜。 在項目中應用DI,你會發現你的代碼會變得異常簡單並且更容易理解 和測試。

DI功能是如何實現的

任何一個有實際意義的應用(肯定比Hello World示例更復雜)都會由 兩個或者更多的類組成,這些類相互之間進行協作來完成特定的業務 邏輯。按照傳統的做法,每個對象負責管理與自己相互協作的對象(即它所依賴的對象)的引用,這將會導致高度耦合和難以測試的代 碼。

舉個例子,考慮下程序清單1.2所展現的Knight類。

程序清單1.2

 

DamselRescuingKnight只能執行RescueDamselQuest 探險任務

可以看到,DamselRescuingKnight在它的構造函數中自行創建了 Rescue DamselQuest。這使得DamselRescuingKnight緊密地 和RescueDamselQuest耦合到了一起,因此極大地限制了這個騎 士執行探險的能力。如果一個少女需要救援,這個騎士能夠召之即 來。但是如果一條惡龍需要殺掉,或者一個圓桌……額……需要滾起 來,那么這個騎士就愛莫能助了。

更糟糕的是,為這個DamselRescuingKnight編寫單元測試將出奇 地困難。在這樣的一個測試中,你必須保證當騎士的 embarkOnQuest()方法被調用的時候,探險的embark()方法也要 被調用。但是沒有一個簡單明了的方式能夠實現這一點。很遺 憾,DamselRescuingKnight將無法進行測試。

耦合具有兩面性(two-headed beast)。一方面,緊密耦合的代碼難以 測試、難以復用、難以理解,並且典型地表現出“打地鼠”式的bug特 性(修復一個bug,將會出現一個或者更多新的bug)。另一方面,一 定程度的耦合又是必須的——完全沒有耦合的代碼什么也做不了。為 了完成有實際意義的功能,不同的類必須以適當的方式進行交互。總 而言之,耦合是必須的,但應當被小心謹慎地管理。

通過DI,對象的依賴關系將由系統中負責協調各對象的第三方組件在 創建對象的時候進行設定。對象無需自行創建或管理它們的依賴關系,如圖1.1所示,依賴關系將被自動注入到需要它們的對象當中 去。 

 

 

圖1.1 

依賴注入會將所依賴的關系自動交給目標對象,而不是讓對象自己去獲取 依賴 為了展示這一點,讓我們看一看程序清單1.3中的BraveKnight,這 個騎士不僅勇敢,而且能挑戰任何形式的探險。

 

程序清單1.3

BraveKnight足夠靈活可以接受任何賦予他的探險任 務 我們可以看到,不同於之前的 DamselRescuingKnight,BraveKnight沒有自行創建探險任 務,而是在構造的時候把探險任務作為構造器參數傳入。這是依賴注 入的方式之一,即構造器注入(constructor injection)。

更重要的是,傳入的探險類型是Quest,也就是所有探險任務都必須 實現的一個接口。所以,BraveKnight能夠響應 RescueDamselQuest、 SlayDragonQuest、 MakeRound TableRounderQuest等任意的Quest實現。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM