Spring in action(Spring實戰) 第四版翻譯,actionspring
第一部分 Spring核心Spring提供了很多功能,但是所有這些功能的基礎是是依賴注入(DI)和面向方面編程(AOP)。
第一章 Springing into action
本章包括:Spring的bean容器探索Spring的核心模組強大的Spring生態系統Spring的新特性
現在是java程式員的好時代。在長達20年的發展過程中,java經曆了一些好時光,也經曆了一些壞時光。儘管有一些粗糙的地方,例如applet,Enterprise javabean(EJB),Java資料對象(JDO),和無數的日誌架構,Java已經成為很多企業軟體的開發平台。Spring是java成為開發平台這個故事的重要組成部分。 早些時候,Spring只是重量級企業java架構的替代品,尤其是EJB。和EJB相比,Spring提供了一個更輕量級、更精簡編程模型。它增強了POJO的能力,這種能力以前只在EJB或者其他java規範中才具備。隨著時間的推移,EJB和J2EE也不斷髮展。EJB開始提供一個簡單的面向POJO的編程模型。現在EJB使用的思想如依賴注入(DI)和面向方面編程(AOP),可以說是來自Spring成功的靈感。 儘管J2EE(現在被稱為JEE)的發展可以趕上Spring,但是Spring從未停止前進。Spring持續進步的領域,即使是現在,JEE剛剛才開始探索,有的甚至是從未涉及。如移動開發,社交API的整合,NoSQL資料庫,雲端運算和大資料。正如我所說的,現在是java程式員的好時代!
這本書是Spring的一個探索。在本章,我們從一個較高的高度看一下Spring,讓你初步感受下Spring的味道。這一章將向你介紹Spring解決類型問題的好方法,本書其餘部分並將圍繞這個方法進行。
1.1 簡化Java開發 Spring是一個開源架構,最初由Rod Johnson建立,並在其寫的《Expert One-on-One: J2EE Design and Development》一書中做了描述。Spring建立的目的是解決公司專屬應用程式開發的複雜性,使以前只能使用EJB解決的問題,現在可以使用普通javabean實現。但是Spring的功能並不局限於伺服器端的開發。任何Java應用程式都可以受益於Spring的簡單、可測試性和松耦合等特性。雖然Spring經常使用bean和JavaBean來表示應用組件,但是這並不意味著一個Spring組件必須遵循JavaBean規範。一個Spring組件可以是任何類型的POJO。在本書中,我採用了一個鬆散的JavaBean的定義,是POJO的同義字。 在本書中你會看到,Spring做了很多事情。但Spring提供的所有功能的根源是基於一些基本的想法,所有想法都關注於Spring的基本任務:Spring簡化Java開發。 這是一個大膽的聲明!很多架構都聲明簡化某些東西。但是Spring旨在簡化Java開發這個廣泛的主題。這就需要更多的解釋。Spring是如何簡化Java開發的?
為了應對java的複雜性,Spring採用了四個關鍵策略:
- 輕量級的、微侵入性的POJO開發
- 使用DI實現松耦合、面向介面編程
- 使用切面和約定實現聲明式編程
- 使用切面和模板減少樣板代碼
Spring所做的幾乎所有事情都可以追溯到上述四個策略上。在本章的其餘部分,我會詳細介紹每一個策略,通過具體的例子來展示Spring是如何?其承諾的:簡化java開發。首先來看下Spring是如何?輕量級的、微侵入性的POJO開發的。
1.1.1 釋放POJO的威力 如果你有幾年的java開發經驗,你可能會遇到這樣一些架構,他們要求你繼承架構的某個類或者實現架構的某個介面。侵入性編程模型的典型例子是EJB2的無狀態Bean。除此之外,在Struts、WebWork、Tapestry的早期版本中,和無數其他Java規範和架構中,都可以很容易看到侵入性編程的例子。 Spring儘可能避免你的應用程式與其API耦合。Spring從來不要求你實現其一個特定的介面或者繼承其一個特定的類。相反,在基於Spring的應用程式中的類通常沒有跡象表明他們正在使用Spring。在最壞的情況下,一個類可能會使用Spring註解,但它仍然是一個POJO。
舉例說明,看下面代碼清單中的HelloWorldBean類:
代碼清單1.1 Spring對HelloWorldBean並不做任何不合理的要求。
package com.habuma.spring;public class HelloWorldBean { public String sayHello() { return "Hello World"; }}
正如您可以看到的,這是一個簡單的,普通的Java類----一個POJO。沒有什麼特別的地方表明它是一個Spring組件。Spring的非入侵編程模型意味著一個類在Spring應用程式中具有的功能,在非Spring應用程式同樣具備。POJO的形式非常簡單,但是其功能可以非常強大。Spring增加POJO功能的一種方式是通過DI(譯者註:依賴注入)將它們組裝起來。讓我們看一下DI是如何?應用中對象之間的松耦合的。
1.1.2 依賴注入依賴注入(dependency injection)一詞聽起來可能有些嚇人,好像是一種複雜的編程技術或者設計模式。但事實證明,DI並不像聽起來的那樣複雜。通過在你的項目中應用DI,你會發現你的代碼將變得更簡單,更容易理解,更容易測試。
DI是如何工作的任何重要的應用程式(比Hello World樣本更複雜的應用)都是由兩個或兩個以上的類相互協作,執行一些商務邏輯的。傳統方式,每個對象負責擷取自己合作對象的引用(這是依賴關係)。這可能會導致代碼高度耦合并且難以測試。例如,看下Knight類,如下所示
代碼清單1.2
package com.springinaction.knights;public class DamselRescuingKnight implements Knight {private RescueDamselQuest quest;public DamselRescuingKnight() {this.quest = new RescueDamselQuest();}public void embarkOnQuest() {quest.embark();}}
正如你所看到的,DamselRescuingKnight(解救少女的騎士。譯者注)類在建構函式中建立了自己的quest:RescueDamselQuest(解救少女任務。譯者注)。這使得DamselRescuingKnight類與RescueDamselQuest類緊密耦合,嚴重限制了騎士所能執行的任務。如果一個少女需要解救,此騎士可以辦到。但是如果此時需要殺死一條龍或者需要一個圓桌,那麼這個騎士只能袖手旁觀了。
更重要的是,為DamselRescuingKnight編寫一個單元測試將會非常難。而且在單元測試中,你要能判斷embarkOnQuest()調用了embark()方法。耦合是一把雙刃劍。一方面,緊密耦合的代碼難以測試,很難重用,難以理解,修複一個bug可能導致出現多個新的bug。另一方面,一定的耦合又是必要的----完全非耦合的代碼做不了任何事情。為了能做一些有用的事情,類之間需要瞭解彼此。耦合是必需的,但應該小心地管理。使用DI,系統中對象間的依賴有第三方來管理。對象不需要建立或擷取它們的依賴項。1.1所示,依賴在需要的時候被注入到對象中。
圖1.1 依賴注入意思是:將依賴給一個對象,而不是一個對象自己獲得這些依賴
為了說明這一點,讓我們看一下下面代碼清單中的BraveKnight類:騎士不僅勇敢,而且能夠完成任何形式的任務。