- Spring快速入門
- 崔彥威 盧欣欣 王倩
- 2816字
- 2020-06-29 17:30:40
2.2 依賴注入DI與控制反轉IOC
本節主要介紹依賴注入與控制反轉的基本概念,理解什么是依賴注入、什么是控制反轉。在此基礎上通過示例動手操作加深理解。
2.2.1 什么是依賴注入
從漢字的字面意思理解,可以把“依賴注入”分為兩個詞,一個是“依賴”,一個是“注入”。那什么是依賴、什么是注入呢?依賴是依靠別人或事物而不能自立或自給,通俗的理解就是,不是自身的,但沒有就活不下去,比如人沒有了空氣、水、陽光,那就活不下去,所以人依賴空氣、水、陽光。注入是之前內部沒有通過外部灌入的。
上面是從字面意思理解了一下依賴注入,接著從編程的角度分析一下。依賴注入是組件之間依賴關系由容器在運行期決定的,即由容器動態地將某個依賴關系注入到組件之中。依賴注入的目的并非為軟件系統帶來更多功能,而是為了解耦,提升組件重用的頻率,并為系統搭建一個靈活、可擴展的平臺。通過依賴注入機制,我們只需要通過簡單的配置,而無須任何代碼就可以指定目標需要的資源,完成自身的業務邏輯,不需要關心具體的資源來自何處、由誰實現。
● 依賴注入是組件之間依賴關系由容器在運行期決定的,即由容器動態地將某個依賴關系注入到組件之中。這句話總結依賴注入的核心原理,比如分別把人(Person)和空氣(Air)都當作一個組件(類),人依賴空氣,那么這個依賴關系不是人和空氣兩個組件關聯的,需要一個容器決定,而且不是一開始就決定的,是運行期決定的。
● 依賴注入的目的并非為軟件系統帶來更多功能,而是為了解耦,提升組件重用的頻率,并為系統搭建一個靈活、可擴展的平臺。這句話是使用依賴注入的目的。使用依賴注入可以進一步解耦,也是軟件設計中高內聚低耦合的體現。
● 通過依賴注入機制,我們只需要通過簡單的配置,而無須任何代碼就可以指定目標需要的資源,完成自身的業務邏輯,不需要關心具體的資源來自何處、由誰實現。這句話是實現依賴注入的方法,通過簡單配置就能實現依賴注入。
理解DI的關鍵是:“誰依賴誰,為什么需要依賴,誰注入誰,注入了什么”,接著使用人和空氣來深入分析一下:
● 誰依賴誰:人依賴空氣。
● 為什么需要依賴:人需要空氣,沒有空氣,人就不存在,就是一個空對象。
● 誰注入誰:人通過容器注入空氣。
● 注入了什么:注入了人所需要的空氣。
2.2.2 什么是控制反轉
與依賴注入一樣,我們還是先從字面意思理解一下控制反轉。它也可以分為兩個詞,一個是“控制”,一個是“反轉”。那什么是控制,什么又是反轉呢?
● 控制:為掌握住對象不使任意活動或超出范圍;或使其按控制者的意愿活動。
● 反轉:向相反的方向轉動。
上面是從中文字面對控制反轉的理解,下面從編程的角度分析一下。IOC意味著將你設計好的對象交給容器控制,而不是傳統的在你的對象內部直接控制。理解IOC的關鍵是:“誰控制誰,控制什么,為何是反轉(有反轉就應該有正轉了),哪些方面反轉了”。我們接著使用人和空氣來深入分析一下:
● 誰控制誰,控制什么:以往我們是通過new關鍵字來創建對象的,比如人(Person)依賴空氣(Air),在Person中如果要使用Air對象,就需要通過New關鍵字來主動創建,在IOC中有一個專門的容器來創建這些對象,即由IOC容器來控制對象的創建。
誰控制誰?當然是IOC容器控制對象了。
控制什么?主要控制了外部資源獲取(不只是對象,還包括文件等)。
● 為何是反轉,哪些方面反轉了:有反轉就有正轉,正轉就是我們通過New主動獲取依賴對象;反轉則是由容器來幫忙創建及注入依賴對象。
為何是反轉?因為由容器幫我們查找及注入依賴對象,對象只是被動地接受依賴對象,所以是反轉。
哪些方面反轉了?依賴對象的獲取被反轉了。Air對象通過容器注入給Person對象。
2.2.3 依賴注入的優缺點
可能有人會納悶為什么只介紹使用依賴注入的優缺點,那控制反轉就沒有優缺點嗎?其實它們是同一個概念的不同角度描述,由于控制反轉概念比較含糊(可能只是理解為容器控制對象這一個層面,很難讓人想到誰來維護對象關系),所以2004年大師級人物Martin Fowler又給出了一個新的名字:“依賴注入”。相對IOC而言,“依賴注入”明確描述了“被注入對象依賴IOC容器配置依賴對象”。
俗話說,每個硬幣都有兩面。同樣,IOC也是有優點和缺點的。
優點,也是使用依賴注入的目的:實現組件之間的解耦,提高程序的靈活性和可維護性,提升組件重用的頻率,并為系統搭建一個靈活、可擴展的平臺。
缺點也是存在的。一是它創建對象的方式變復雜了。二是因為使用反射來創建對象,所以在效率上會有些損耗。但相對于程序的靈活性和可維護性來說,這點損耗是微不足道的。三是使用XML進行配置時太復雜,一旦類有改變,XML就需要改變。有了注解之后,與使用XML進行配置相比簡單很多。
2.2.4 IOC實例
光說不練假把式,特別是IT技術,經常會出現看能看懂但寫不出來的尷尬局面。上面分析了一下依賴注入與控制反轉,本節將通過示例來加深理解。這里還是使用人與空氣的例子。
人依賴空氣,在傳統的方式創建兩個類:一個是Person類,一個是CleanAir類。

上面兩個類實現了依賴的關系,還有就是注入。在了解注入之前,我們還有一個問題要思考。有這樣一句話:世界上唯一不變的就是變化。之前干凈的空氣不復存在,而Person依賴的不再是CleanAir,而是比CleanAir更有內涵的DirtyAir。如果還是按照上面的方式來,那就需要在增加一個DirtyAir類的同時修改Person。這種強依賴有很大的弊端,一個地方變化引起其他地方變化,而且改變的只是Air,但Person也要改變。怎么樣才能盡量減少修改的地方呢?于是面向接口的編程出現了。下面先定義一個接口IAir,類CleanAir實現接口IAir,在Person中不再直接依賴CleanAir,而是依賴接口IAir,這樣即使是DirtyAir也只需要給Person修改不同的Air就行了。這個注入的過程,利用Spring框架只需要改一下配置即可實現。

上面定義IAir接口算是對依賴關系的優化,降低了人與空氣的耦合度,但是并沒有使用New關鍵字創建對象,只是定義了依賴關系。下面用Spring實現注入。
(1)創建一個Maven Project,archetype選擇quickstart,如圖2-2所示。

圖2-2
(2)創建之后,既然要使用Spring框架來實現注入,那肯定要在項目中引入Spring框架,配置pom.xml,添加依賴。
① 在properties節點配置要引入Spring的版本號,這里用的是5.0.0.RELEASE。
<spring.version>5.0.0.RELEASE</spring.version>
② 引入。
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency>
(3)實現依賴注入。
前面創建的IAir接口、Person類、CleanAir類、DirtyAir類實現了依賴關系,但是怎么讓Spring框架識別到呢?不可能把各個類創建好就結束了,還需要進行配置才能讓Spring知道哪些是組件。這里對Person類、CleanAir類、DirtyAir類在上面定義的基礎上進行修改。

在上面的代碼中使用了@Component將類注解成組件,使用@Autowired將IAir類型對象注入Person中。CleanAir類、DirtyAir類都實現了IAir接口,怎么讓Person具體注入哪個對象呢?使用@Qualifier關鍵字來進行區分,這里使用的是qualifier=dirtyair。同時這些組件定義之后還要告訴Spring框架組件位置在哪,所以在scr/main/resources下新建了ApplicationContext.xml進行配置。

(4)測試。
在main中獲取到應用上下文,通過getBean方法獲取Person對象,然后調用Breath()方法。不了解ClassPathXmlApplicationContext、getBean這些方法也沒關系,在后面的章節會有詳細介紹。

輸出結果:
DirtyAir
如果想使用CleanAir對象,只需要把Person類中@Qualifier注解value的值改為CleanAir對應的beanId:cleanair。
(5)小結
參考上面的示例思考2.2.1和2.2.2節中的概念,就會發現依賴注入、控制反轉其實也不難。理解了依賴注入、控制反轉對后面Spring框架的學習會有更大的幫助。
- 軟件項目估算
- Reporting with Visual Studio and Crystal Reports
- Mastering ServiceStack
- INSTANT OpenCV Starter
- Rake Task Management Essentials
- AIRAndroid應用開發實戰
- iOS開發實戰:從零基礎到App Store上架
- Hands-On Enterprise Automation with Python.
- KnockoutJS Starter
- Visual Foxpro 9.0數據庫程序設計教程
- 從0到1:HTML5 Canvas動畫開發
- PHP+MySQL動態網站開發從入門到精通(視頻教學版)
- 3D Printing Designs:The Sun Puzzle
- Building UIs with Wijmo
- Effective DevOps with AWS