Spring環境搭建及簡單demo

1. Spring框架簡介(以下這段話可用於面試求職)

Spring爲JavaEE開發提供了一個輕量級的解決方案,主要表現爲,

  • IOC(或者叫做DI)的核心機制,提供了bean工廠(Spring容器),降低了業務對象替換的複雜性,提高了組件之間的解耦。
  • AOP的將一些通用任務,如安全、事務、日誌等集中進行管理,提高了複用性和管理的便捷性
  • ORM和DAO提供了與第三方持久層框架的良好整合,簡化了底層數據訪問。
  • 提供了優秀的Web MVC框架。

可以說Spring是貫穿表現層、業務層、持久層,爲javaEE提供一站式解決方案的框架。此外,使用Spring還有如下好處,

  • 低侵入設計,代碼污染極低。
  • 基於Spring框架的應用,可以獨立於各種應用服務器,實現 write once, run anywhere,
  • Spring可以與第三方框架良好整合(如ORM,DAO等模塊與其他框架整合),但同時Spring提供了高度開放性,應用不會被強制依賴Spring,開發者可以自由選擇Spring的部分或者全部。

Spring並不侷限於中間層,而是爲系統各層都提供了企業級解決方案(例如IOC可以

使用Spring框架可以帶來諸多好處,例如進行數據庫事務處理,遠程調用,JMS消息處理,JMX操作處理,而這些處理都不需要開發人員直接使用相關API(JDBC, JMX, JMS 等)

2.Sping架構

Spring框架是分模塊存在,除了最核心的Spring Core Container(即Spring容器)是必要模塊之外,其他模塊都是可選,視需要而定。

官方文檔Spring4.0的架構圖中,包含了20多個子模塊,大致可以分爲四類 1)核心容器(Core Container) 2)數據訪問和集成(Data Access/Integration) 3)Web 4)AOP。

本質上Spring可以總結爲以下七個模塊。

其中常用模塊的大致功能如下。

核心容器:核心容器提供 Spring 框架的基本功能。核心容器的主要組件是 BeanFactory,它是工廠模式的實現。BeanFactory 使用控制反轉 (IOC) 模式將應用程序的配置和依賴性規範與實際的應用程序代碼分開。

Spring 上下文:Spring 上下文是一個配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企業服務,例如 JNDI、EJB、電子郵件、國際化、校驗和調度功能。

Spring AOP:通過配置管理特性,Spring AOP 模塊直接將面向切面的編程功能集成到了 Spring 框架中。可以將一些通用任務,如安全、事務、日誌等集中進行管理,提高了複用性和管理的便捷性。

Spring DAO:爲JDBC DAO 抽象層提供了有意義的異常層次結構,可用該結構來管理異常處理和不同數據庫供應商拋出的錯誤消息。異常層次結構簡化了錯誤處理,並且極大地降低了需要編寫的異常代碼數量(例如打開和關閉連接)。Spring DAO 的面向 JDBC 的異常遵從通用的 DAO 異常層次結構。

Spring ORM:Spring 框架插入了若干個 ORM 框架,從而提供了 ORM 的對象關係工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有這些都遵從 Spring 的通用事務和 DAO 異常層次結構。

Spring Web 模塊:Web 上下文模塊建立在應用程序上下文模塊之上,爲基於 Web 的應用程序提供了上下文。所以,Spring 框架支持與 Jakarta Struts 的集成。Web 模塊還簡化了處理多部分請求以及將請求參數綁定到域對象的工作。

Spring MVC 框架:MVC 框架是一個全功能的構建 Web 應用程序的 MVC 實現。通過策略接口,MVC 框架變成爲高度可配置的,MVC 容納了大量視圖技術,其中包括 JSP、Velocity、Tiles、iText 和 POI。

 3.環境搭建

首先需要下載Spring框架 spring-framework-4.0.4.RELEASE-dist,4.0.4版官方地址爲 http://repo.springsource.org/libs-release-local/org/springframework/spring/4.0.4.RELEASE/ (如果覺得太慢也可以去國內網站下載)

此外,還需要下載一個必要組件 commons-logging-1.1.3-bin ,可以在http://commons.apache.org/官網下載也可以在國內網站下載。

其他諸如log4j之類的並不是必須下載的。

下載好以上兩個壓縮包。在workspace下新建一個lib目錄作爲user library。將Spring壓縮包解壓之後,將libs目錄下的 *RELEASE.jar(共21個)都拷貝到你的workspace下的lib目錄;將commons包也解壓,將根目錄的*.1.3.jar(共3個)都拷貝到lib目錄下。

之後在Eclipse中添加一個user library,添加成功後的效果如下,

4.簡單demo及控制反轉(IOC)和依賴注入(DI)簡介

J2EE提倡面向接口編程,Spring也是針對的接口編程,即在代碼中只使用規範(即接口),而將真正的實現類配置在文件中,由Spring的配置文件來決定將會使用哪一個實現類,這也叫做控制反轉(IOC)或者依賴注入(DI)。

現在我們假設有這麼一個場景, 我們指定一類人去使用一類斧頭,不同的人可以使用不同的斧頭,當然其效果不一樣。

按照J2EE的建議,首先我們需要定義“人”和“斧頭”兩個規範,即創建兩個接口,

斧頭接口,

1 package spi;
2 
3 public interface Axe {
4     public String chop();
5 }
斧頭接口的一個實現,

 package spi;
2 
3 public class StoneAxe implements Axe { 
4     public String chop() {
5         return "石斧砍柴好慢";
6     }
7 }
人接口

package spi;
2 
3 public interface Person {
4     public void useAxe();
5 }
人接口的一個實現,

 1 package spi;
 2 
 3 public class Chinese implements Person {
 4     private Axe axe;
 5     public void setAxe(Axe axe) {
 6         this.axe = axe;
 7     }
 8     public void useAxe() {
 9         System.out.println("我打算去砍點柴火");
10         System.out.println(axe.chop());
11     }
12 }

下面要寫一個測試類,使用Person接口的一個實現類的對象,去調用Axe的一個實現類的對象,

按照傳統編程方式,我們一般會寫成下面這樣,

 package spi;
 2 
 3 public class BeanTest {
 4     public static void main(String[] args) {
 5         Chinese p = new Chinese();
 6         StoneAxe axe = new StoneAxe();
 7         p.setAxe(axe);
 8         p.useAxe();
 9     }
10 }

重點是第6行和第7行,即Chinese類和StoneAxe類耦合在了java代碼中,如果現在需求有變,我們在這裏要使用一種新的斧頭,即Axe有一個新的實現類SteelAxe,那麼就必須修改這裏的代碼, SteelAxe axe = new SteelAxe(); 這對於代碼維護其實並不方便。 對於這個問題,Spring的解決方案是將上面的步驟放在配置文件中,具體實現方法是這樣的,

首先創建一個配置文件,名字自定義即可,

<?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4     xsi:schemaLocation="http://www.springframework.org/schema/beans
 5         http://www.springframework.org/schema/beans/spring-beans.xsd">
 6     <bean id="chinese" class="spi.Chinese">
 7         <property name="axe" ref="stoneAxe" />
 8     </bean>
 9     <bean id="stoneAxe" class="spi.StoneAxe" />
10     <bean id="win" class="javax.swing.JFrame" />
11     <bean id="date" class="java.util.Date" />
12 </beans>

可以看到配置文件中定義了上面兩個接口的實現類的具體包路徑,其中stoneAxe還被定義成了Chinese類的一個屬性,

有了這個配置文件之後,Spring就可以在底層利用java反射,首先創建出兩個類對象(Chinese和StoneAxe),接着馬上執行對象的setter方法,依據配置文件中各個類的依賴關係去初始化每個對象的屬性,而這個過程,正是上面傳統編程中的StoneAxe axe = new StoneAxe();p.setAxe(axe);這兩部!

下面看看Spring方式在測試代碼中的寫法,

package spi;
 2 
 3 import org.springframework.context.ApplicationContext;
 4 import org.springframework.context.support.ClassPathXmlApplicationContext;
 5 
 6 public class BeanTest {
 7     public static void main(String[] args) {
 8         ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
 9         Person p = ctx.getBean("chinese", Person.class);
10         p.useAxe();
11     }
12 }
執行結果,

1 我打算去砍點柴火
2 石斧砍柴好慢

可以看到,在測試代碼中,完全沒有了Chinese和StoneAxe兩個類的耦合依賴關係,轉而將依賴關係放在了上面的XML文件中,底層通過java反射的方式進行初始化。

即,將java代碼中對象間的依賴關係的控制權交給了Spring配置文件,由Spring來生成對象,並且設置對象間的依賴關係,這就是控制反轉(IOC)或者叫依賴注入(DI)。

Spring自動生成對象(可禁用)和設置依賴關係是最基本的功能。

Spring的IOC(或DI)機制,極大地降低了組件間的耦合,例如對於上面的需求變更,我們只需要在XML文件中新增一個bean節點,並設置好依賴關係即可,而測試代碼不需要任何改變!

新增Axe的實現類,

 package spi;
2 
3 public class SteelAxe implements Axe { 
4     public String chop() {
5         return "鋼斧砍柴好快";
6     }
7 }
修改Spring配置文件,

<?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4     xsi:schemaLocation="http://www.springframework.org/schema/beans
 5         http://www.springframework.org/schema/beans/spring-beans.xsd">
 6     <bean id="chinese" class="spi.Chinese">
 7         <property name="axe" ref="steelAxe" />
 8     </bean>
 9     <bean id="stoneAxe" class="spi.StoneAxe" />
10     <bean id="steelAxe" class="spi.SteelAxe" />
11     <bean id="win" class="javax.swing.JFrame" />
12     <bean id="date" class="java.util.Date" />
13 </beans>
執行測試類結果,

1 我打算去砍點柴火
2 鋼斧砍柴好快

5.設值注入和構造注入

對於依賴注入,有兩種方式,一種是設置注入,即上面XML配置文件中設置<property />標籤的方式,這種方法本質上是利用反射調用對象的setter方式進行初始化。

另外,還可以使用構造注入的方式,即在XML配置文件中使用<constructor-arg />標籤,不過這種方式要求有對應的構造方法才行。

對於上面的例子,首先我們要讓Chinese類有一個構造方法,

1     public Chinese(Axe axe) {
2         this.axe = axe;
3     }
接着我們將XML配置文件中的<peroperty>標籤用<constructor-arg>標籤替換,

<bean id="chinese" class="spi.Chinese">
2         <!--  <property name="axe" ref="stoneAxe" /> -->
3         <constructor-arg ref="stoneAxe" />
4     </bean>

我們將得到一樣的結果,只是實現的方式不一樣而已。對於設值注入和構造注入兩種方式如何選擇呢,

一般的,如果對依賴關係無需變化地注入,儘量採用構造注入。其他依賴關係的注入則考慮採用設值方式注入。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章