本來地址:SpringMVC乾貨系列:從零搭建SpringMVC+mybatis(三):Spring兩大核心之IOC/DI學習
博客地址:tengj.top/java
上篇講了SpringMVC的實現原理以及經常使用的註解,其實裏面都用到的spring的核心概念,那就是IOC/DI,今天給你們介紹下這核心概念IOC/DI。spring
分享Iteye的開濤這位技術牛人對Spring框架的IOC的理解,寫得很是通俗易懂。編程
Ioc—Inversion of Control,即「控制反轉」,不是什麼技術,而是一種設計思想。在Java開發中,Ioc意味着將你設計好的對象交給容器控制,而不是傳統的在你的對象內部直接控制。如何理解好Ioc呢?理解好Ioc的關鍵是要明確「誰控制誰,控制什麼,爲什麼是反轉(有反轉就應該有正轉了),哪些方面反轉了」,那咱們來深刻分析一下:mybatis
誰控制誰,控制什麼:傳統Java SE程序設計,咱們直接在對象內部經過new進行建立對象,是程序主動去建立依賴對象;而IoC是有專門一個容器來建立這些對象,即由Ioc容器來控制對 象的建立;誰控制誰?固然是IoC 容器控制了對象;控制什麼?那就是主要控制了外部資源獲取(不僅是對象包括好比文件等)。mvc
爲什麼是反轉,哪些方面反轉了:有反轉就有正轉,傳統應用程序是由咱們本身在對象中主動控制去直接獲取依賴對象,也就是正轉;而反轉則是由容器來幫忙建立及注入依賴對象;爲什麼是反轉?由於由容器幫咱們查找及注入依賴對象,對象只是被動的接受依賴對象,因此是反轉;哪些方面反轉了?依賴對象的獲取被反轉了。app
用圖例說明一下,傳統程序設計如圖2-1,都是主動去建立相關對象而後再組合起來:框架
當有了IoC/DI的容器後,在客戶端類中再也不主動去建立這些對象了,如圖所示:
ide
IoC 不是一種技術,只是一種思想,一個重要的面向對象編程的法則,它能指導咱們如何設計出鬆耦合、更優良的程序。傳統應用程序都是由咱們在類內部主動建立依賴對象,從而致使類與類之間高耦合,難於測試;有了IoC容器後,把建立和查找依賴對象的控制權交給了容器,由容器進行注入組合對象,因此對象與對象之間是 鬆散耦合,這樣也方便測試,利於功能複用,更重要的是使得程序的整個體系結構變得很是靈活。post
其實IoC對編程帶來的最大改變不是從代碼上,而是從思想上,發生了「主從換位」的變化。應用程序本來是老大,要獲取什麼資源都是主動出擊,可是在IoC/DI思想中,應用程序就變成被動的了,被動的等待IoC容器來建立並注入它所須要的資源了。單元測試
IoC很好的體現了面向對象設計法則之一—— 好萊塢法則:「別找咱們,咱們找你」;即由IoC容器幫對象找相應的依賴對象並注入,而不是由對象主動去找。
DI—Dependency Injection,即「依賴注入」:組件之間依賴關係由容器在運行期決定,形象的說,即由容器動態的將某個依賴關係注入到組件之中。依賴注入的目的並不是爲軟件系統帶來更多功能,而是爲了提高組件重用的頻率,併爲系統搭建一個靈活、可擴展的平臺。經過依賴注入機制,咱們只須要經過簡單的配置,而無需任何代碼就可指定目標須要的資源,完成自身的業務邏輯,而不須要關心具體的資源來自何處,由誰實現。
理解DI的關鍵是:「誰依賴誰,爲何須要依賴,誰注入誰,注入了什麼」,那咱們來深刻分析一下:
誰依賴於誰:固然是應用程序依賴於IoC容器;
爲何須要依賴:應用程序須要IoC容器來提供對象須要的外部資源;
誰注入誰:很明顯是IoC容器注入應用程序某個對象,應用程序依賴的對象;
注入了什麼:就是注入某個對象所須要的外部資源(包括對象、資源、常量數據)。
IoC和DI由什麼關係呢?其實它們是同一個概念的不一樣角度描述,因爲控制反轉概念比較含糊(可能只是理解爲容器控制對象這一個層面,很難讓人想到誰來維護對象關係),因此2004年大師級人物Martin Fowler又給出了一個新的名字:「依賴注入」,相對IoC 而言,「依賴注入」明確描述了「被注入對象依賴IoC容器配置依賴對象」。
看過不少對Spring的Ioc理解的文章,好多人對Ioc和DI的解釋都晦澀難懂,反正就是一種說不清,道不明的感受,讀完以後依然是一頭霧水,感受就是開濤這位技術牛人寫得特別通俗易懂,他清楚地解釋了IoC(控制反轉) 和DI(依賴注入)中的每個字,讀完以後給人一種豁然開朗的感受。我相信對於初學Spring框架的人對Ioc的理解應該是有很大幫助的。
上面介紹了IOC跟DI的概念,接着,我將概括一下使用Spring裝備bean的基礎知識,由於DI是Spring的最基本要素。因此在開發的基於Spring的應用時,咱們隨時都在使用這些技術。
當描述bean如何進行裝配時,Spring具備很是大的靈活性,它提供了三種主要的裝配機制:
雖然看上去提供三種可選的配置方案會使Spring變得複雜。其實,你能夠根據實際項目選擇,對了,上面這三種其實能夠混合搭配,目前博主使用的就是自動裝配(也就是註解)+XML混合使用。這也是目前比較流行的方式。
下面將主要介紹自動化裝備Bean+XML的混合搭配
當前來講,相比較前面兩種顯示配置,從便利性方面來看,最強大的仍是Spring的自動化配置。
Spring從兩個角度來實現自動化裝配:
組件掃描和自動裝配組合在一塊兒就能發揮出強大的威力,他們可以將你的顯示配置下降到最少。
這裏組件掃描咱們經過在XML裏面使用Spring context命名空間的
配置以下:
<!-- 加了下面2局就能夠直接使用spring註解 -->
<!-- 自動掃描的包名 -->
<context:component-scan base-package="com.tengj.demo" />
<!-- 默認的註解映射的支持 -->
<mvc:annotation-driven />複製代碼
context:component-scan裏面的 base-package指明瞭被掃描的包的路徑是在com.tengj.demo下面的全部類
其中mvc:annotation-driven 是開啓默認的註解映射的支持,這樣就能認到被使用的註解。
咱們在com.tengj.demo下面建立一個UserController控制類:
@Controller
public class UserController{
@Autowired
UserService userService;
}複製代碼
UserService是咱們的一個接口,代碼以下:
public interface UserService {
public void addUser() throws Exception;
}複製代碼
UserServiceImpl是UserService的實現類:
@Service("userService")
public class UserServiceImpl implements UserService{
@Override
public void addUser() throws Exception {
System.out.println("新增用戶");
}
}複製代碼
寫個單元測試類來驗證這個userService是否已經自動注入了
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:spring/applicationContext.xml"})
public class UserConTrollerTest {
@Autowired
UserService userService;
@Test
public void checkServiceIsNull(){
Assert.assertNotNull(userService);
}
}複製代碼
UserConTrollerTest使用了Spring的SpringJUnit4ClassRunner,以便在測試開始的時候自動建立Spring的應用上下文,註解@ContextConfiguration會告訴它須要在UserConTrollerTest中加載配置。因此讀取applicationContext.xml配置文件,配置文件裏面有
爲了證實這一點,在測試代碼中有一個UserService類型的屬性,而且這個屬性帶有@Autowired註解,以便於將UserService bean注入到測試代碼之中。最後,會有一個簡單的測試方法斷言userService屬性不爲null。若是它不爲null的話,就意味着Spring可以發現UserService類,自動在Spring上下文中將其建立爲bean並將其注入到測試代碼之中。
在代碼中右鍵執行Junit Test,若是執行以下是綠色的就表示成功。
這就是一個簡單的DI注入測試,是否是以爲很方便,要注入什麼屬性只要定義一下屬性。剩下都交給Spring容器來搞定。Junit單元測試寫法後續會專門寫一篇來介紹,這也是很是重要的一個驗證本身所寫代碼是否正確的手段。
一直以爲本身寫的不是技術,而是情懷,一篇篇文章是本身這一路走來的痕跡。靠專業技能的成功是最具可複製性的,但願個人這條路能讓你少走彎路,但願我能幫你抹去知識的蒙塵,但願我能幫你理清知識的脈絡,但願將來技術之巔上有你也有我。
剛來掘金當專欄做者,歡迎關注,後面陸續分享更多幹貨文章