spring in action 第一章
spring是從何而來?
spring是為了解決企業級應用開發的複雜性而建立的,使用spring可以讓簡單的javaBeans實作以前EJB才能完成的事情。而且spring不僅僅局限于伺服器端開發,任何java應用都能在簡單性,可測試性和松耦合性等方面從spring中獲益。spring可以做很多事情。但歸根結底,支撐spring的僅僅是少許的基本理念,所有的理念都可以追溯到spring的的最根本使命上:簡化java開發。
降低java開發的複雜性,spring采取了以下四個政策:
1.基于POJO(簡單java類)的輕量級和最小侵入性程式設計
2.通過依賴注入和面向接口實作松耦合
3.基于切面和慣例進行聲明式程式設計
4.通過切面和模闆減少樣闆式代碼
1簡化java開發
1.1激發pojo潛能
在以前的架構中我們的程式或許會被他們的規則焊死。而spring盡力避免自身api弄亂我們的代碼。spring不會強迫你你實作spring規範的接口或者繼承spring規範的類,相反,在基于spring建構的應用中,它的類通常沒有任何痕迹表明你使用了spring。最壞的場景是,一個類或許會使用spring注解,但它仍然是POJO(簡單java類)
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnL4gTN1UTN0QTM3IzMwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
就像是上圖的樣子,在HelloWorldBean上沒有任何過分的要求。這就是一個POJO(簡單Java類),沒有任何證據表明它是一個spring元件。spring的非侵入程式設計模型意味着這個類在spring應用和非spring應用中都可以發揮同樣的作用。
監管POJO看起來很簡單,但spring可以通過DI(依賴注入)來裝配它們。讓我們看看DI是如何幫助應用對象之間保持松耦合的。
1.2依賴注入
依賴注入看起來一個nb plus的詞語,現在也已經演變成為一項複雜的程式設計技巧或設計模式理念。其實依賴注入并不像聽上去那樣複雜。在項目中應用DI,你會發現你的代碼會變得異常簡單而且更加容易了解和測試。
任何一個項目都會有兩個或者更多的類組成,這些類互相協作完成特定的業務邏輯。按照一貫做法,每個對象負責管理與自己互相協作的對象的引用,這将會導緻高度耦合和難以測試的代碼。
如上DamselResuingKnight隻能執行DamselResuingQuest的探險任務。這兩個類之間的耦合度太高了,以至于少女守護者隻能做很單一的任務,他能随時保護女孩但是如果要去殺掉惡龍或者給女孩打飯呢,那這個守護者是做不到這些的。
更糟糕的是為這個類編寫單元測試出奇的困難,編寫測試我們要保證守護者被召喚來的時候他的方法會被調用,沒有簡單明了的方法可以實作這一點。
耦合具有兩面性。一方面,緊密耦合的代碼難以測試,難以複用,難以了解,并且典型的表現出“打地鼠”式的bug特性(修複一個bug會有更多bug出現)。另一方面耦合是不可避免的,為了完成特定任務總有類在互動,是以我們應該謹慎管理耦合。
通過DI,對象的依賴關系由系統中的第三方元件在建立對象的時候進行設定,對象無需建立或者管理它們的依賴關系。
如上圖這次我們傳入一個quest他不是一個具體的探險任務,而是一個任務接口,隻要實作了這個接口的探險任務BraveKnight都可以勝任。這樣BraveKnight沒有和任何特定探險任務有耦合,這就是DI的最大收益松耦合。
我們為BraveKnight編寫一個測試是很輕松地,隻需給quest一個mock實作即可
知道了spring松耦合的原理那麼我們該注入quest了有下圖一個殺龍的探險任務
可以看到這個類實作了Quest接口那麼它可以注入BraveKnight,我們不僅要把這個類注入到BraveKnight裡,而且要把stream注入到這個類裡面。spring将建立元件之間的協作行為稱為裝配(wiring)。spring多種裝配方式,第一種xml檔案
第二種java配置
兩種帶來的DI收益是一樣的,并且它們都符合上面的松耦合規則,被裝配對象不知道要裝配什麼具體的對象,但是這些對象都有相同的接口,在裝配時才知道是什麼類型。
接下來要使用裝配好的對象,這時需要spring應用上下文,它全權負責對象的建立群組裝。spring有多種應用上下文,這裡選擇ClassPathXmlApplicationContext這個類加載類路徑下的一個或多個xml檔案,如下圖
這裡可以看出來我們不知道knight的具體細節隻有xml檔案知道,我們不知道誰在執行任務,更不知道在執行什麼樣的任務。
1.3應用切面(這裡大都引用原文,原文很清晰)
DI能夠保證對象之間的松耦合,而面向切面允許程式設計允許把遍布在各處的功能分離出可重用元件
例子見原文這裡了解原理即可
1.4使用模闆消除樣闆式代碼
有時我們會将一些代碼一遍又一遍得寫,比如JDBC的代碼如圖
下面是spring jdbcTemplate的代碼
模闆代碼可以讓你隻關注代碼自身的職責。
2.容納你的bean
在spring應用中,你的應用對象生存于spring容器中,spring容器負責建立對象并且裝配它們,配置和管理它們的整個生命周期,從建立到死亡(從new 到 finalize)
2.1使用上下文
這裡不談web應用,剩餘的上下文使用方法如下
最後我們隻需要用getBean方法擷取類就可以了
2.1bean的生命周期
一般的java bean生命周期從new開始一直到沒有引用的時候會被垃圾回收機制自動回收
相比而言spring bean生命周期要複雜得多,正确了解spring bean 生命周期非常重要,因為你或許要利用spring提供的擴充點來自定義bean的建立過程。下圖展示了bean裝載到spring上下文中的一個完整的生命周期過程
spring的功能很強大,上面所述的DI AOP 和消除版樣式代碼隻是spring的簡化java開發的基本功能,它還有許多超乎想象的功能。