1. 程式人生 > >(一)《Spring實戰》——Spring核心

(一)《Spring實戰》——Spring核心

有意 技術分享 似的 簡單的 pix 發布應用 .com span size

《Spring實戰》(第4版)

    技術分享圖片

第一章:Spring之旅

    技術分享圖片

1. 簡化Java開發

為了降低Java開發的復雜性,Spring采取了以下4種關鍵策略:

  • 基於POJO的輕量級和最小侵入性編程;
  • 通過依賴註入和面向接口實現松耦合;
  • 基於切面和慣例進行聲明式編程;
  • 通過切面和模板減少樣板式代碼。

1.1 激發POJO的潛能

  在基於Spring構建的應用中,它的類通常沒有任何痕跡表明你使用了Spring。最壞的場景是,一個類或許會使用Spring註解,但它依舊是POJO。

  Spring賦予POJO魔力的方式之一就是通過DI來裝配它們。

1.2 依賴註入(DI)

  耦合是必須的,但應當被小心謹慎地管理。

  創建應用組件之間協作的行為通常稱為裝配(wiring)。Spring有多種裝配bean的方式,采用XML是很常見的一種裝配方式。

        技術分享圖片

                KnightMain.java加載包含Knight的Spring上下文

  這裏的main() 方法基於knights.xml文件創建了Spring應用上下文。隨後它調用該應用上下文獲取一個ID為knight的bean。得到Knight 對象的引用後,只需簡單調用embarkOnQuest() 方法就可以執行所賦予的探險任務了。註意這個類完全不知道我們的英雄騎士接受哪種探險任務,而且完全沒有意識到這是由BraveKnight

來執行的。只有knights.xml文件知道哪個騎士執行哪種探險任務。

  Spring還支持使用Java來描述配置。

         技術分享圖片

            Spring提供了基於Java的配置,可作為XML的替代方案

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

                    技術分享圖片

         依賴註入會將所依賴的關系自動交給目標對象,而不是讓對象自己去獲取依賴

1.3 應用切面

  DI能夠讓相互協作的軟件組件保持松散耦合,而面向切面編程(aspect-oriented programming,AOP)允許你把遍布應用各處的功能分離出來形成可重用的組件。

  面向切面編程往往被定義為促使軟件系統實現關註點的分離一項技術。系統由許多不同的組件組成,每一個組件各負責一塊特定功能。除了實現自身核心的功能之外,這些組件還經常承擔著額外的職責。諸如日誌、事務管理和安全這樣的系統服務經常融入到自身具有核心業務邏輯的組件中去,這些系統服務通常被稱為橫切關註點,因為它們會跨越系統的多個組件。

  • 實現系統關註點功能的代碼將會重復出現在多個組件中。這意味著如果你要改變這些關註點的邏輯,必須修改各個模塊中的相關實現。即使你把這些關註點抽象為一個獨立的模塊,其他模塊只是調用它的方法,但方法的調用還是會重復出現在各個模塊中。
  • 組件會因為那些與自身核心業務無關的代碼而變得混亂。一個向地址簿增加地址條目的方法應該只關註如何添加地址,而不應該關註它是不是安全的或者是否需要支持事務。

            技術分享圖片

        在整個系統內,關註點(例如日誌和安全)的調用經常散布到各個模塊中,而這些關註點並不是模塊的核心業務

  AOP能夠使這些服務模塊化,並以聲明的方式將它們應用到它們需要影響的組件中去。所造成的結果就是這些組件會具有更高的內聚性並且會更加關註自身的業務,完全不需要了解涉及系統服務所帶來復雜性。總之,AOP能夠確保POJO的簡單性。

  如下圖所示,我們可以把切面想象為覆蓋在很多組件之上的一個外殼。應用是由那些實現各自業務功能的模塊組成的。借助AOP,可以使用各種功能層去包裹核心業務層。這些層以聲明的方式靈活地應用到系統中,你的核心應用甚至根本不知道它們的存在。這是一個非常強大的理念,可以將安全、事務和日誌關註點與核心業務邏輯相分離。

            技術分享圖片

            利用AOP,系統範圍內的關註點覆蓋在它們所影響組件之上

1.4 使用模板消除樣板式代碼

  因為使用Java API而導致的樣板式代碼,樣板式代碼的一個常見範例是使用JDBC訪問數據庫查詢數據。在許多編程場景中往往都會導致類似的樣板式代碼,JMS、JNDI和使用REST服務通常也涉及大量的重復代碼。

  Spring旨在通過模板封裝來消除樣板式代碼。Spring的JdbcTemplate使得執行數據庫操作時,避免傳統的JDBC樣板代碼成為了可能。

          技術分享圖片

2. 容納你的Bean

在基於Spring的應用中,你的應用對象生存於Spring容器(container)中。Spring容器負責創建對象,裝配它們,配置它們並管理它們的整個生命周期,從生存到死亡(在這裏,可能就是newfinalize())

容器是Spring框架的核心。Spring容器使用DI管理構成應用的組件,它會創建相互協作的組件之間的關聯。毫無疑問,這些對象更簡單幹凈,更易於理解,更易於重用並且更易於進行單元測試。

Spring容器並不是只有一個。Spring自帶了多個容器實現,可以歸為兩種不同的類型。bean工廠(由org.springframework.beans.factory.BeanFactory 接口定義)是最簡單的容器,提供基本的DI支持。應用上下文(由org.springframework.context.ApplicationContext 接口定義)基於BeanFactory構建,並提供應用框架級別的服務,例如從屬性文件解析文本信息以及發布應用事件給感興趣的事件監聽者。

2.1 使用應用上下文

Spring自帶了多種類型的應用上下文。下面羅列的幾個是你最有可能遇到的。

  • AnnotationConfigApplicationContext 從一個或多個基於Java的配置類中加載Spring應用上下文。
  • AnnotationConfigWebApplicationContext 從一個或多個基於Java的配置類中加載Spring Web應用上下文。
  • ClassPathXmlApplicationContext 從類路徑下的一個或多個XML配置文件中加載上下文定義,把應用上下文的定義文件作為類資源。
  • FileSystemXmlapplicationcontext 從文件系統下的一個或多個XML配置文件中加載上下文定義。
  • XmlWebApplicationContext 從Web應用下的一個或多個XML配置文件中加載上下文定義。

無論是從文件系統中裝載應用上下文還是從類路徑下裝載應用上下文,將bean加載到bean工廠的過程都是相似的。例如,如下代碼展示了如何加載一個FileSystemXmlApplicationContext:

      技術分享圖片

  類似地,你可以使用ClassPathXmlApplicationContext 從應用的類路徑下加載應用上下文:

      技術分享圖片

  使用FileSystemXmlApplicationContext 和使用ClassPathXmlApp-licationContext 的區別在於:FileSystemXmlApplicationContext 在指定的文件系統路徑下查找knight.xml文件;而ClassPathXmlApplicationContext 是在所有的類路徑(包含JAR文件)下查找 knight.xml文件。

  應用上下文準備就緒之後,我們就可以調用上下文的getBean() 方法從Spring容器中獲取bean。

2.2 bean的生命周期

  在傳統的Java應用中,bean的生命周期很簡單。使用Java關鍵字new進行bean實例化,然後該bean就可以使用了。一旦該bean不再被使用,則由Java自動進行垃圾回收。

  相比之下,Spring容器中的bean的生命周期就顯得相對復雜多了。正確理解Spring bean的生命周期非常重要,因為你或許要利用Spring提供的擴展點來自定義bean的創建過程。下圖展示了bean裝載到Spring應用上下文中的一個典型的生命周期過程。

      技術分享圖片

正如你所見,在bean準備就緒之前,bean工廠執行了若幹啟動步驟。我們對上圖進行詳細描述:

  • 1.Spring對bean進行實例化;
  • 2.Spring將值和bean的引用註入到bean對應的屬性中;
  • 3.如果bean實現了BeanNameAware 接口,Spring將bean的ID傳遞給setBean-Name() 方法;
  • 4.如果bean實現了BeanFactoryAware 接口,Spring將調用setBeanFactory() 方法,將BeanFactory容器實例傳入;
  • 5.如果bean實現了ApplicationContextAware 接口,Spring將調用setApplicationContext() 方法,將bean所在的應用上下文的引用傳入進來;
  • 6.如果bean實現了BeanPostProcessor 接口,Spring將調用它們的post-ProcessBeforeInitialization() 方法;
  • 7.如果bean實現了InitializingBean 接口,Spring將調用它們的after-PropertiesSet() 方法。類似地,如果bean使用init-method 聲明了初始化方法,該方法也會被調用;
  • 8.如果bean實現了BeanPostProcessor 接口,Spring將調用它們的post-ProcessAfterInitialization() 方法;
  • 9.此時,bean已經準備就緒,可以被應用程序使用了,它們將一直駐留在應用上下文中,直到該應用上下文被銷毀;
  • 10.如果bean實現了DisposableBean 接口,Spring將調用它的destroy() 接口方法。同樣,如果bean使用destroy-method 聲明了銷毀方法,該方法也會被調用。

3. 俯瞰Spring風景線

3.1 Spring模塊

在Spring 4.0中,Spring框架的發布版本包括了20個不同的模塊,每個模塊會有3個JAR文件(二進制類庫、源碼的JAR文件以及JavaDoc的JAR文件)。

                  技術分享圖片

這些模塊依據其所屬的功能可以劃分為6類不同的功能:

            技術分享圖片

3.2 Spring Portfolio

  Spring遠不是Spring框架所下載的那些。如果僅僅停留在核心的Spring框架層面,我們將錯過Spring Portfolio所提供的巨額財富。整個Spring Portfolio包括多個構建於核心Spring框架之上的框架和類庫。概括地講,整個Spring Portfolio幾乎為每一個領域的Java開發都提供了Spring編程模型。

技術分享圖片

(一)《Spring實戰》——Spring核心