摘 要 針對傳統的J
EE架構方案常常無法讓人滿意
程序過於復雜
難以測試和維護成本高
根據企業實際需求
本文探討了一種輕量級的J
EE應用框架Spring
它用更加輕量
更加靈活的基礎設施取代了EJB
在此對Spring背後的反向控制原理和面向切面編程技術進行了比較深入研究
並與傳統實現進行對比
顯示了這種框架具有大大降低開發成本
可測試等優點
關鍵詞 Spring
反向控制
面向切面編程
POJO
依賴注入
引言
在J
EE的整個發展歷程中
現在正是一個非常時刻
從很多方面來說
J
EE都是一個偉大的成功
它成功地在從前沒有標准的地方建立了標准
大大提升了企業級軟件的開放程度
並且得到了整個行業和開發者的廣泛認可
然而
J
EE在一些方面已經開始捉襟見肘
J
EE應用開發的成本通常很高
J
EE應用項目至少和從前的非J
EE項目一樣容易失敗——如果不是更容易失敗的話
這樣的失敗率高得讓人難以接受
在這樣的失敗率之下
軟件開發幾乎變成了碰運氣
而在J
EE遭遇失敗的場景中
EJB通常都扮演著重要的角色
因此
J
EE社群不斷地向著更簡單的解決方案
更少使用EJB的方向發展[
]
然而
每個應用程序都需要一些基礎設施
拒絕使用EJB並不意味著拒絕EJB所采用的基礎設施解決方案
那麼
如何利用現有的框架來提供這些基礎設施服務呢
伴隨著這個問題的提出
一個輕量級的J
EE解決方案出現了
這就是Spring Framework
Spring是為簡化企業級系統開發而誕生的
Spring框架為J
EE應用常見的問題提供了簡單
有效的解決方案
使用Spring
你可以用簡單的POJO(Plain Old Java Object)來實現那些以前只有EJB才能實現的功能
這樣不只是能簡化服務器端開發
任何Java系統開發都能從Spring的簡單
可測試和松耦合特征中受益
可以簡單的說
Spring是一個輕量級的反向控制(IoC)和面向切面編程(AOP)容器框架[
]
Spring IoC
借助於依賴注入設計模式
使得開發者不用理會對象自身的生命周期及其關系
而且能夠改善開發者對J
EE模式的使用
Spring AOP
借助於Spring實現的攔截器
開發者能夠實現以聲明的方式使用企業級服務
比如安全性服務
事務服務等
Spring IoC和 Spring ; AOP組合
一起形成了Spring
這樣一個有機整體
使得構建輕量級的J
EE架構成為可能
而且事實證明
非常有效
沒有Spring IoC的Spring AOP是不完善的
沒有Spring AOP的Spring IoC是不健壯的
本文是以Spring架構的成功的實際商務系統項目為背景
闡述了反向控制原理和面向切面的編程技術在Spring框架中的應用
同時抽取適量代碼示意具體應用
並和傳統開發模式進行對比
展示了Spring framework的簡單
高效
可維護等優點
Spring IoC
反向控制原理
反向控制是Spring框架的核心
但是
反向控制是什麼意思?到底控制的什麼方面被反向了呢?
年美國專家Martin Fowler發表了一篇論文《Inversion of Control Containers and the Dependency Injection pattern》闡述了這個問題
他總結說是獲得依賴對象的方式反向了
根據這個啟示
他還為反向控制提出了一個更貼切的名字
Dependency Injection(DI 依賴注入)
通常
應用代碼需要告知容器或框架
讓它們找到自身所需要的類
然後再由應用代碼創建待使用的對象實例
因此
應用代碼在使用實例之前
需要創建對象實例
然而
IoC模式中
創建對象實例的任務交給IoC容器或框架(實現了IoC設計模式的框架也被稱為IoC容器)
使得應用代碼只需要直接使用實例
這就是IoC
相對IoC 而言
依賴注入
的確更加准確的描述了這種設計理念
所謂依賴注入
即組件之間的依賴關系由容器在運行期決定
形象的來說
即由容器動態的將某種依賴關系注入到組件之中
IoC在Spring中的實現
任何重要的系統都需要至少兩個相互合作的類來完成業務邏輯
通常
每個對象都要自己負責得到它的合作(依賴)對象
你會發現
這樣會導致代碼耦合度高而且難於測試
使用IoC
對象的依賴都是在對象創建時由負責協調系統中各個對象的外部實體提供的
這樣使軟件組件松散連接成為可能
下面示意了Spring IoC 應用
步驟如下
(
)定義Action接口
並為其定義一個execute方法
以完成目標邏輯
多年前
GoF在《Design Pattern
Elements of Reusable Object
Oriented Software》一書中提出
Programming to an Interface
not an implementation
的原則
這裡首先將業務對象抽象成接口
正是為了實施這個原則
(
)類UpperAction實現Action接口
在此類中
定義一個String型的域message
並提供相應的setter和getter方法
實現的execute方法如下
public String execute (String str) {
return (getMessage () + str)
toUpperCase () ;
}
(
)編寫Spring配置文件(bean
xml)
<beans>
<bean id=
TheAction
class=
net
chen
spring
qs
UpperAction
>
<property name=
message
>
<value>HeLLo</value>
</property>
</bean>
</beans>
(
)測試代碼
public void testQuickStart () {
ApplicationContext ctx=new
FileSystemXmlApplicationContext (
bean
xml
);
Action a= (Action) ctx
getBean (
TheAction
);
System
out
println (a
execute (
Rod Johnson
));
}
上面的測試代碼中
我們根據
bean
xml
創建了一個ApplicationContext實例
並從此實例中獲取我們所需的Action實現
運行測試代碼
我們看到控制台輸出
……
HELLO ROD JOHNSON
仔細觀察一下上面的代碼
可以看到
(
)我們的組件並不需要實現框架指定的接口
因此可以輕松的將組件從Spring中脫離
甚至不需要任何修改
這在基於EJB框架實現的應用中是難以想象的
(
)組件間的依賴關系減少
極大改善了代碼的可重用性
Spring的依賴注入機制
可以在運行期為組件配置所需資源
而無需在編寫組件代碼時就加以指定
從而在相當程度上降低了組件之間的耦合
Spring給我們帶來了如此這般的好處
那麼
反過來
讓我們試想一下
如果不使用Spring框架
回到我們傳統的編碼模式
情況會是怎樣呢?
首先
我們必須編寫一個配置文件讀取類
以實現Message屬性的可配置化
其次
得有一個Factory模式的實現
並結合配置文件的讀寫完成Action的動態加載
於是
我們實現了一個ActionFactory來實現這個功能
public class ActionFactory {
public static Action getAction (String actionName) {Properties pro = new Properties ();
try {
pro
load (new FileInputStream (
config
properties
));
String actionImplName =(String)pro
get(actionName);
String actionMessage =(String) pro
get (actionName+
_msg
);
Object obj =Class
forName (actionImplName)
newInstance ();
BeanUtils
setProperty(obj
message
actionMessage);
return (Action) obj;
} catch (FileNotFoundException e) {
……
}
}
配置文件則采用properties文件形式如下所示
TheAction=net
chen
spring
qs
UpperAction
TheAction_msg=HeLLo
測試代碼也作相應修改
現在不論實現的好壞
總之通過上面新增的多行代碼
終於實現了類似的功能
如果現在有了一個新的需求
這樣這個ActionFactory每次都新建一個類的實例
顯然這對系統性能不利
考慮到我們的兩個Action都是線程安全的
修改一下ActionFactory
保持系統中只有一個Action實例供其它線程調用
另外Action對象創建後
需要做一些初始化工作
修改一下ActionFactory
使其在創建Action實例之後
隨即就調用Action
init方法執行初始化
Action的處理這樣就差不多了
下面我們來看看另外一個Factory
……
往往這些系統開發中最常見的需求
會導致我們的代碼迅速膨脹
而Spring IoC的出現
則大大緩解了這樣的窘境
通過以上實例
可以看出
Spring IoC為我們提供了如下幾方面的優勢
(
)應用組件不需要在運行時尋找其協作者
因此更易於開發和編寫應用
(
)由於借助於IoC容器管理組件的依賴關系
使得應用的單元測試和集成測試更利於展開
(
)通常
在借助於IoC容器關系業務對象的前提下
很少需要使用具體IoC容器提供的API
這使得集成現有的遺留應用成為可能
因此
通過使用IoC能夠降低組件之間的耦合度
最終
能夠提高類的重用性
利於測試
而且更利於整個產品或系統集成和配置
From:http://tw.wingwit.com/Article/program/Java/ky/201311/28485.html