Spring詳解(一):簡介
Spring Framework創始人:Rod Johnson. 計算機專業本科,音樂學博士。有著相當豐富的C/C++技術背景的Rod早在1996年就開始了對Java伺服器端技術的研究。
輪子理論推崇者:
- 輪子理論:不用重複發明輪子
- IT 行業:直接使用寫好的程式碼
Spring框架宗旨:不重新發明技術,讓原有技術使用起來更加方便。
Spring優點:
- 方便解耦,簡化開發,通過Spring提供的IoC容器,我們可以將物件之間的依賴關係交由Spring進行控制,避免硬編碼造成的程式耦合度高。
- AOP程式設計的支援,通過Spring提供的AOP功能,方便進行面向切面程式設計。
- 宣告式事務的支援,在Spring中,我們可以從單調煩悶的事務管理程式碼中解脫出來,通過宣告式方式靈活地進行事務的管理,提高開發效率和質量。
- 方便程式的測試,可以用非容器依賴的程式設計方式進行幾乎所有的測試工作。
- 方便整合各種優秀框架,Spring提供了對各種優秀框架的直接支援。
1. Spring 核心功能
- IOC/DI:控制反轉/依賴注入
- AOP:面向切面的程式設計
- 宣告式事務
2. Spring Framework Runntime
整個Spring框架按其所屬功能可以劃分為五個主要模組,這五個模組幾乎為企業應用提供了所需的一切,從持久層、業務層到表現層都擁有相應的支援
2.1 Spring Framework Test
Spring可以用非容器依賴的程式設計方式進行幾乎所有的測試工作,支援JUnit和TestNG等測試框架。
2.2 Spring Framework Core Container
Spring Framework 核心容器。它是Spring啟動最基本的條件。
- Spring-Beans:模組下的所有類主要解決了三件事:Bean 的定義、Bean 的建立以及對 Bean 的解析。
- Spring-Core:Spring的核心模組實現了IoC的功能,它將類和類之間的依賴從程式碼中脫離出來,用配置的方式進行依賴關係描述。 由IoC容器負責類的建立,管理,獲取等。BeanFactory介面是Spring框架的核心介面,實現了容器很多核心的功能。
- Spring-Context:Context模組構建於核心模組之上,擴充套件了BeanFactory的功能,包括國際化,資源載入,任務排程,管理註解等多項功能。ApplicationContext是Context模組的核心介面。
- Spring-SpEL:表示式語言(Expression Language)是統一表達式語言(EL)的一個擴充套件,支援設定和獲取物件屬性,呼叫物件方法,運算元組、集合等。使用它可以很方便的通過表示式和Spring IoC容器進行互動。
2.3 Spring Framework AOP
Spring AOP模組提供了滿足AOP Alliance規範的實現,還整合了AspectJ這種AOP語言級的框架。通過AOP能降低耦合。
2.4 Spring Framework Aspects
切面AOP依賴的包
2.5 Spring Framework Data Access/Integration
Spring封裝資料訪問層相關內容,該模組包括了JDBC、ORM、OXM、JMS和事務管理
- 事務模組:該模組用於Spring管理事務,只要是Spring管理物件都能得到Spring管理事務的好處,無需在程式碼中進行事務控制了,而且支援程式設計和宣告性的事務管理。
- JDBC模組:提供了一個JBDC的樣例模板,使用這些模板能消除傳統冗長的JDBC編碼還有必須的事務控制,而且能享受到Spring管理事務的好處。
- ORM模組:提供與流行的“物件-關係”對映框架的無縫整合,包括Hibernate、JPA、MyBatis等。而且可以使用Spring事務管理,無需額外控制事務。
- OXM模組:提供了一個對Object/XML對映實現,將java物件對映成XML資料,或者將XML資料對映成java物件,Object/XML對映實現包括JAXB、Castor、XMLBeans和XStream。
- JMS模組:用於JMS(Java Messaging Service),提供一套 “訊息生產者、訊息消費者”模板用於更加簡單的使用JMS,JMS用於用於在兩個應用程式之間,或分散式系統中傳送訊息,進行非同步通訊。
2.6 Spring Framework Web
需要Spring 完成Web相關功能時需要使用的模組.
- Spring-Web模組提供基本的面向Web的整合功能,如多部分檔案上傳功能,使用Servlet偵聽器的IoC容器的初始化以及面向Web的應用程式上下文。它還包含一個HTTP客戶端和Spring遠端處理支援的Web相關部分。
- Spring-Webmvc模組(也稱為Web-Servlet模組)包含Spring的模型 - 檢視 - 控制器(MVC)和Web應用程式的REST Web服務實現。Spring的MVC框架提供了域模型程式碼和Web表單之間的清晰分離,並且與Spring框架的所有其他功能整合在一起。
- Spring-WebSocket:Spring對WebSocket封裝的包
- Spring-Portlet
3. Spring 概念
從Spring3開始把Spring框架的功能拆分成多個jar,然而Spring2及以前都是一個jar包。
3.1 容器(Container)
實際上,容器是Spring框架實現功能的核心,容器不只是幫我們建立了物件那麼簡單,它負責了物件整個的生命週期的管理——建立、裝配、銷燬。關於Spring的這個容器你最常聽聞的一個術語就是IOC容器。所謂IOC,是一種叫控制反轉的程式設計思想,網上有很通俗易懂的總結,我就不胡亂闡述了。總之一句話,我的應用程式裡不用再過問物件的建立和管理物件之間的依賴關係了,都讓IOC容器給代勞吧,也就是說,我把物件建立、管理的控制權都交給Spring容器,這是一種控制權的反轉,所以Spring容器才能稱為IOC容器。不過這裡要澄清一點:並不是說只有Spring的容器才叫IOC容器,基於IOC容器的框架還有很多,並不是Spring特有的。
3.2 BeanFactory介面(老版本)
BeanFactory,這是最簡單的容器,只能提供基本的DI功能:對Bean的定義、建立、解析功能.
我們來看一看BeanFactory介面:
package org.springframework.beans.factory;
public interface BeanFactory {
/**
* 用來引用一個例項,或把它和工廠產生的Bean區分開,就是說,如果一個FactoryBean的名字為a,那麼,&a會得到那個Factory
*/
String FACTORY_BEAN_PREFIX = "&";
/*
* 四個不同形式的getBean方法,獲取例項
*/
Object getBean(String name) throws BeansException;
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
boolean containsBean(String name); // 是否存在
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;// 是否為單例項
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;// 是否為原型(多例項)
boolean isTypeMatch(String name, Class<?> targetType)
throws NoSuchBeanDefinitionException;// 名稱、型別是否匹配
Class<?> getType(String name) throws NoSuchBeanDefinitionException; // 獲取型別
String[] getAliases(String name);// 根據例項的名字獲取例項的別名
}
具體:
- 4個獲取例項的方法。getBean的過載方法。
- 4個判斷的方法。判斷是否存在,是否為單例、原型,名稱型別是否匹配。
- 1個獲取型別的方法、一個獲取別名的方法。根據名稱獲取型別、根據名稱獲取別名。一目瞭然!
3.3 ApplicationContext介面(新版本)
ApplicationContext是BeanFactory的子介面,BeanFactory的功能在ApplicationContext中都有。繼承了BeanFactory後派生而來的ApplicationContext,它能提供更多企業級的服務,例如解析配置文字資訊等等,這也是ApplicationContext最常見的應用場景。有了上下文物件,我們就能向容器註冊需要Spring管理的物件了。
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
/**
* Return the unique id of this application context.
* @return the unique id of the context, or {@code null} if none
*/
String getId();
/**
* Return a name for the deployed application that this context belongs to.
* @return a name for the deployed application, or the empty String by default
*/
String getApplicationName();
/**
* Return a friendly name for this context.
* @return a display name for this context (never {@code null})
*/
String getDisplayName();
/**
* Return the timestamp when this context was first loaded.
* @return the timestamp (ms) when this context was first loaded
*/
long getStartupDate();
/**
* Return the parent context, or {@code null} if there is no parent
* and this is the root of the context hierarchy.
* @return the parent context, or {@code null} if there is no parent
*/
ApplicationContext getParent();
/**
* Expose AutowireCapableBeanFactory functionality for this context.
* <p>This is not typically used by application code, except for the purpose of
* initializing bean instances that live outside of the application context,
* applying the Spring bean lifecycle (fully or partly) to them.
* <p>Alternatively, the internal BeanFactory exposed by the
* {@link ConfigurableApplicationContext} interface offers access to the
* {@link AutowireCapableBeanFactory} interface too. The present method mainly
* serves as a convenient, specific facility on the ApplicationContext interface.
* <p><b>NOTE: As of 4.2, this method will consistently throw IllegalStateException
* after the application context has been closed.</b> In current Spring Framework
* versions, only refreshable application contexts behave that way; as of 4.2,
* all application context implementations will be required to comply.
* @return the AutowireCapableBeanFactory for this context
* @throws IllegalStateException if the context does not support the
* {@link AutowireCapableBeanFactory} interface, or does not hold an
* autowire-capable bean factory yet (e.g. if {@code refresh()} has
* never been called), or if the context has been closed already
* @see ConfigurableApplicationContext#refresh()
* @see ConfigurableApplicationContext#getBeanFactory()
*/
AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;
}
3.4 控制反轉 IOC
Ioc—Inversion of Control,即“控制反轉”,不是什麼技術,而是一種設計思想。在Java開發中,Ioc意味著將你設計好的物件交給容器控制,而不是傳統的在你的物件內部直接控制。如何理解好Ioc呢?理解好Ioc的關鍵是要明確“誰控制誰,控制什麼,為何是反轉(有反轉就應該有正轉了),哪些方面反轉了”,那我們來深入分析一下:
- 誰控制誰,控制什麼:傳統Java SE程式設計,我們直接在物件內部通過new進行建立物件,是程式主動去建立依賴物件;而IoC是有專門一個容器來建立這些物件,即由Ioc容器來控制對 象的建立;誰控制誰?當然是IoC 容器控制了物件;控制什麼?那就是主要控制了外部資源獲取(不只是物件包括比如檔案等)。
- 為何是反轉,哪些方面反轉了:有反轉就有正轉,傳統應用程式是由我們自己在物件中主動控制去直接獲取依賴物件,也就是正轉;而反轉則是由容器來幫忙建立及注入依賴物件;為何是反轉?因為由容器幫我們查詢及注入依賴物件,物件只是被動的接受依賴物件,所以是反轉;哪些方面反轉了?依賴物件的獲取被反轉了。
控制反轉IoC(Inversion of Control)是說建立物件的控制權進行轉移,以前建立物件的主動權和建立時機是由自己把控的,而現在這種權力轉移到第三方,比如轉移交給了IoC容器,它就是一個專門用來建立物件的工廠,你要什麼物件,它就給你什麼物件,有了 IoC容器,依賴關係就變了,原先的依賴關係就沒了,它們都依賴IoC容器了,通過IoC容器來建立它們之間的關係。
用圖例說明一下,傳統程式設計如圖,都是主動去建立相關物件然後再組合起來:
當有了IoC/DI的容器後,在客戶端類中不再主動去建立這些物件了,如圖
3.5 依賴注入 DI
DI—Dependency Injection,即“依賴注入”:元件之間依賴關係由容器在執行期決定,形象的說,即由容器動態的將某個依賴關係注入到元件之中。依賴注入的目的並非為軟體系統帶來更多功能,而是為了提升元件重用的頻率,併為系統搭建一個靈活、可擴充套件的平臺。通過依賴注入機制,我們只需要通過簡單的配置,而無需任何程式碼就可指定目標需要的資源,完成自身的業務邏輯,而不需要關心具體的資源來自何處,由誰實現。
3.6 面向切面的程式設計 AOP
面向切面程式設計的基本思想是在極少影響原程式的程式碼的前提下,在程式中的某些地方,使用某些方式,不可見的(即不在原程式中新增其他程式碼)為原程式切入一些額外的功能。
AOP,是一種程式設計技術,它允許程式設計師對橫切關注點或橫切典型的職責分界線的行為進行模組化。