一、背景
springframework 從最初的2.5版本發展至今,期間已經發生了非常多的修正及優化。許多新特性及模塊的出現,使得整個框架體系顯得越趨龐大,同時也帶來了學習及理解上的困難。
本文闡述了一些要點,並配合一些代碼樣例,這有助於快速理解 spring 框架。
二、spring架構
核心容器層
Core 模塊
提供了框架的基本組成部分,包括 IoC 及依賴注入功能。
Bean 模塊
實現 Bean 管理,包括自動裝配機制等功能; 其中BeanFactory是一個工廠模式的實現。
Context 模塊
建立在 Core 和 Bean 模塊基礎上,通常用於訪問配置及定義的任何對象。ApplicationContext 是上下文模塊的重要接口。
SpEL 模塊
表達式語言模塊提供了運行時進行查詢及操作一個對象的表達式機制。
數據訪問/集成
JDBC 模塊
用於替代繁瑣的 JDBC API 的抽象層。
ORM 模塊
對象關系數據庫映射抽象層,可集成JPA,JDO,Hibernate,iBatis。
OXM 模塊
XML消息綁定抽象層,支持JAXB,Castor,XMLBeans,JiBX,XStream。
JMS 模塊
Java消息服務模塊,實現消息生產-消費之類的功能。
Transaction 模塊
事務模塊為各種 POJO 支持編程式和聲明式事務管理。
Web應用
Web 模塊
Web MVC 提供了基於 模型-視圖-控制器 的基礎web應用框架。
servlet 模塊
實現了統一的監聽器以及和面向web應用的上下文,用以初始化 IoC 容器。
Web-Portlet
實現在 portlet 環境中實現 MVC。
Web-Socket 模塊
為 WebSocket連接 提供支持。
其他模塊
AOP 模塊
提供了面向切面的編程實現,允許開發者通過定義方法攔截器及切入點對代碼進行無耦合集成,它實現了關注點分離。
Aspects 模塊
提供了與 AspectJ 的集成,這是一個功能強大且成熟的面向切面編程(AOP)框架。
Instrumentation 模塊
實現instrumentation支持,一般用以應用服務器的監測。
Messaging 模塊
為STOMP 提供了支持,STOMP協議是一種簡單的文本定向消息協議,是 WebSocket 的子協議。
測試
支持 JUnit 、TestNG 框架的集成
三、基礎工程
后續的工作將基於樣例工程展開,首先需要准備JDK、Java IDE如Eclipse、Maven環境,此類工作較為簡單,在此不作贅述。
- 創建Maven項目;
- 配置Spring依賴;
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.2.RELEASE</version> </dependency>
3. 編寫配置文件及測試代碼;
core-beans.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="randomID" class="org.springfoo.core.bean.RandomID" scope="prototype" init-method="init" destroy-method="destroy"> </bean> <bean id="message" class="org.springfoo.core.bean.Message" scope="prototype"> <property name="content" value="Hello sam" /> <property name="sender" value="bob" /> <property name="reciever" value="sam" /> </bean> </beans>
POJO定義
public class Message { private String content; private String sender; private String reciever; public String getContent() { return content; } public void setContent(String content) { this.content = content; } ...
測試代碼
private static void tryAppContext() { ApplicationContext context = new ClassPathXmlApplicationContext("core-beans.xml"); Message message = context.getBean(Message.class); System.out.println(message); }
四、IOC 容器
IOC 即控制反轉,將對象的生命周期管理、關系依賴通過容器實現,實現解耦。
ApplicationContext是最關鍵的入口,其包括幾種實現:
-
FileSystemXmlApplicationContext,從 XML 文件中加載被定義的 bean對象,基於文件系統路徑加載配置;
-
ClassPathXmlApplicationContext,從 XML 文件中加載被定義的 bean對象,基於類路徑加載配置;
-
WebXmlApplicationContext,從 XML 文件中加載被定義的 bean對象,基於 web 應用程序范圍加載配置;
五、Bean 管理
5.1 作用域
singleton
每一個 Spring IoC 容器中保持一個單一實例(默認)。
prototype
bean 的實例可為任意數量。
request
該作用域將 bean 的定義限制為 HTTP 請求。只在 web-aware Spring ApplicationContext 的上下文中有效。
session
該作用域將 bean 的定義限制為 HTTP 會話。 只在web-aware Spring ApplicationContext的上下文中有效。
global-session
該作用域將 bean 的定義限制為全局 HTTP 會話。只在 web-aware Spring ApplicationContext 的上下文中有效。
5.2 生命周期
Bean 的初始化及銷毀對應 init 及 destroy 兩個行為,可通過實現 InitializingBean/DisposableBean 接口觀察對象的初始化及銷毀時機。
代碼片段:
public void afterPropertiesSet() throws Exception {
System.out.println(this + "-- properties set"); } public void init() { System.out.println(this + "-- init"); } public void destroy() { System.out.println(this + "-- destroy"); }
為了使spring獲得 destroy 行為的監視機會,需要注冊JVM關閉回調:
context.registerShutdownHook();
init/destroy攔截
實現 BeanPostProcessor 接口,並注冊到配置文件
<bean class="xxx.MyBeanPostProcessor" />
5.3 bean模板
通常可將一組屬性歸集為bean模板以實現復用
<!-- template -->
<bean id="template" abstract="true">
<property name="support" value="true" />
<property name="count" value="10" />
</bean>
<bean id="tplbean" class="org.springfoo.core.bean.TplBean" parent="template">
<property name="message" value="I'm inheritted from template" />
</bean>
POJO 定義
public class TplBean {
private String message; private boolean support; private Integer count; ...
六、依賴注入
6.1 簡單例子
-
People 包含 Hand/Foot/Body;
-
Hand/Foot 通過構造參數注入;
-
Body通過屬性參數注入;
beans.xml
<bean id="people" class="org.springfoo.di.bean.People" scope="prototype">
<constructor-arg ref="foot"/>
<constructor-arg ref="hand"/>
<property name="body" ref="body"/>
</bean>
<bean id="foot" class="org.springfoo.di.bean.Foot" scope="prototype">
<property name="label" value="FOOT" />
</bean>
<bean id="hand" class="org.springfoo.di.bean.Hand" scope="prototype">
<property name="label" value="HAND" />
</bean>
<bean id="body" class="org.springfoo.di.bean.Body" scope="prototype">
<property name="label" value="BODY---BB" />
</bean>
People.java
public class People {
private Foot foot;
private Hand hand;
private Body body;
public People(){
}
public People(Foot foot, Hand hand) {
super();
this.foot = foot;
this.hand = hand;
}
public Foot getFoot() {
return foot;
}
public void setFoot(Foot foot) {
this.foot = foot;
}
public Hand getHand() {
return hand;
}
...
其余略
6.2 注入集合
可通過配置一組值的方式實現集合注入
集合POJO
@SuppressWarnings("rawtypes")
public class CollectionBean {
private List list;
private Set set;
private Map map;
private Properties prop;
public List getList() {
return list;
}
public void setList(List list) {
this.list = list;
}
public Set getSet() {
return set;
}
public void setSet(Set set) {
this.set = set;
}
public Map getMap() {
return map;
}
public void setMap(Map map) {
this.map = map;
}
public Properties getProp() {
return prop;
}
public void setProp(Properties prop) {
this.prop = prop;
}
}
beans.xml
<bean id="collection" class="org.springfoo.di.bean.CollectionBean">
<property name="list">
<list>
<value>APPLE</value>
<value>ORANGE</value>
<value>PINAPPLE</value>
</list>
</property>
<property name="set">
<set>
<value>TABLE</value>
<value>CHAIR</value>
</set>
</property>
<property name="map">
<map>
<entry key="b" value="BEER" />
<entry key="j" value="JUICE" />
</map>
</property>
<property name="prop">
<props>
<prop key="sp">Single Player</prop>
<prop key="tp">Two Player</prop>
</props>
</property>
</bean>
6.3 自動裝配
POJO定義
public class AutoWireBean {
private String message;
private Body body;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Body getBody() {
return body;
}
public void setBody(Body body) {
this.body = body;
}
}
beans.xml
<bean id="autowire" class="org.springfoo.di.bean.AutoWireBean"
autowire="byName" scope="prototype">
<property name="message" value="okok autowire going..."/>
</bean>
autowire類型
- byName, 通過屬性名稱與配置中bean名稱配對
- byType, 通過屬性類型與配置中bean類型配對
- constructor, 通過構造函數中bean類型配對
七、總結
至此,關於 spring 的核心概念已經介紹完畢,接下來就是如何在實踐中深化了。
相信只要理解了基礎理念,在后續的項目中自然會得心應手,畢竟萬變不離其宗。


