Spring學習(0)——Spring架構師對Spring的介紹

關於Spring Framework,今年夏天你可能已經聽見很多的議論。在本文中,我將試圖解釋Spring能完成什麼,和我怎麼會認爲它能幫助你開發J2EE應用程序。 

又來一個framework? 

你可能正在想“不過是另外一個的framework”。當已經有許多開放源代碼(和專有) J2EE framework時,爲什麼你還要耐下心子讀這篇文章或去下載Spring Framework? 

我相信Spring是獨特的,有幾個原因: 



它關注的領域是其他許多流行的Framework未曾關注的。Spring要提供的是一種管理你的業務對象的方法。 

Spring既是全面的又是模塊化的。Spring有分層的體系結構,這意味着你能選擇僅僅使用它任何一個獨立的部分,而它的架構又是內部一致。因此你能從你的學習中,得到最大的價值。例如,你可能選擇僅僅使用Spring來簡單化JDBC的使用,或用來管理所有的業務對象。 

它的設計從一開始就是要幫助你編寫易於測試的代碼。Spring是使用測試驅動開發的工程的理想框架。 


Spring不會給你的工程添加對其他的框架依賴。Spring也許稱得上是個一站式解決方案,提供了一個典型應用所需要的大部分基礎架構。它還涉及到了其他framework沒有考慮到的內容。 

儘管它僅僅是一個從2003年2月纔開始的開源項目,但Spring有深厚的歷史根基。這個開源工程是起源自我在2002年晚些時候出版的《Expert One-on-One J2EE設計與開發》書中的基礎性代碼。這本書展示了Spring背後的基礎性架構思想。然而,對這個基礎架構的概念可以追溯到2000年的早些時候,並且反映了我爲一系列商業工程開發基礎結構的成功經驗。 

2003年1月,Spring已經落戶於SourceForge上了。現在有10個開發人員,其中6個是高度投入的積極分子。 

Spring架構上的好處 

在我們進入細節之前,讓我們來看看Spring能夠給工程帶來的種種好處: 



Spring能有效地組織你的中間層對象,不管你是否選擇使用了EJB。如果你僅僅使用了Struts或其他爲J2EE的 API特製的framework,Spring致力於解決剩下的問題。 

Spring能消除在許多工程中常見的對Singleton的過多使用。根據我的經驗,這是一個很大的問題,它降低了系統的可測試性和麪向對象的程度。 

通過一種在不同應用程序和項目間一致的方法來處理配置文件,Spring能消除各種各樣自定義格式的屬性文件的需要。曾經對某個類要尋找的是哪個魔法般的屬性項或系統屬性感到不解,爲此不得不去讀Javadoc甚至源編碼?有了Spring,你僅僅需要看看類的JavaBean屬性。 Inversion of Control的使用(在下面討論)幫助完成了這種簡化。 

通過把對接口編程而不是對類編程的代價幾乎減少到沒有,Spring能夠促進養成好的編程習慣。 

Spring被設計爲讓使用它創建的應用儘可能少的依賴於他的APIs。在Spring應用中的大多數業務對象沒有依賴於Spring。 

使用Spring構建的應用程序易於單元測試。 

Spring能使EJB的使用成爲一個實現選擇,而不是應用架構的必然選擇。你能選擇用POJOs或local EJBs來實現業務接口,卻不會影響調用代碼。 

Spring幫助你解決許多問題而無需使用EJB。Spring能提供一種EJB的替換物,它們適用於許多web應用。例如,Spring能使用AOP提供聲明性事務管理而不通過EJB容器,如果你僅僅需要與單個數據庫打交道,甚至不需要一個JTA實現。 

Spring爲數據存取提供了一個一致的框架,不論是使用的是JDBC還是O/R mapping產品(如Hibernate)。 


Spring確實使你能通過最簡單可行的解決辦法來解決你的問題。而這是有有很大價值的。 

Spring做了些什麼? 

Spring提供許多功能,在此我將依次快速地展示其各個主要方面。 

任務描述 

首先,讓我們明確Spring範圍。儘管Spring覆蓋了許多方面,但我們對它應該涉什麼,什麼不應該涉及有清楚的認識。 

Spring的主要目的是使J2EE易用和促進好編程習慣。 

Spring不重新輪子。因此,你發現在Spring中沒有logging,沒有連接池,沒有分佈式事務調度。所有這些東西均有開源項目提供(例如我們用於處理所有日誌輸出的Commons Logging以及Commons DBCP),或由你的應用程序服務器提供了。出於同樣的的原因,我們沒有提供 O/R mapping層。對於這個問題已經有了像Hibernate和JDO這樣的優秀解決方案。 

Spring的目標就是讓已有的技術更加易用。例如,儘管我們沒有底層事務協調處理,但我們提供了一個抽象層覆蓋了JTA或任何其他的事務策略。 

Spring沒有直接和其他的開源項目競爭,除非我們感到我們能提供新的一些東西。例如,象許多開發人員一樣,我們從來沒有對Struts感到高興過,並且覺得到在MVC web framework中還有改進的餘地。在某些領域,例如輕量級的IoC容器和AOP框架,Spring確實有直接的競爭,但是在這些領域還沒有已經較爲流行的解決方案。(Spring在這些領域是開路先鋒。) 

Spring也得益於內在的一致性。所有的開發者都在唱同樣的的讚歌,基礎想法依然與Expert One-on-One J2EE設計與開發中提出的差不多。 並且我們已經能夠在多個領域中使用一些中心的概念,例如Inversion of Control。 

Spring在應用服務器之間是可移植的。當然保證可移植性總是一種挑戰,但是我們避免使用任何平臺特有或非標準的東西,並且支持在WebLogic,Tomcat,Resin,JBoss,WebSphere和其他的應用服務器上的用戶。 

Inversion of Control 容器 

Spring設計的核心是 org.springframework.beans 包, 它是爲與JavaBeans一起工作而設計的。 這個包一般不直接被用戶使用,而是作爲許多其他功能的基礎。 

下一個層面高一些的抽象是"Bean Factory"。一個Spring bean factory 是一個通用的Factory,它使對象能夠按名稱獲取,並且能管理對象之間的關係。 

Bean factories 支持兩種模式的對象: 



Singleton:在此模式中,有一個具有特定名稱的共享對象實例,它在查找時被獲取。這是默認的,而且是最爲經常使用的。它對於無狀態對象是一種理想的模式。 

Prototype:在此模式中,每次獲取將創建一個獨立的對象。例如,這可以被用於讓用戶擁有他們自己的對象。 



由於 org.springframwork.beans.factory.BeanFactory是一個簡單的接口,它能被大量底層存儲方法實現。你能夠方便地實現你自己的BeanFactory,儘管很少用戶需要這麼做。最爲常用的BeanFactory定義是: 



XmlBeanFactory: 可解析簡單直觀的定義類和命名對象屬性的XML結構。 我們提供了一個DTD來使編寫更容易。 

ListableBeanFactoryImpl:提供瞭解析存放在屬性文件中的bean定義的能力,並且可通過編程創建BeanFactories。 


每個bean定義可能是一個POJO(通過類名和JavaBean初始屬性定義),或是一個FactoryBean。FactoryBean接口添加了一個間接層。通常,這用於創建使用AOP或其他方法的代理對象:例如,添加聲明性事務管理的代理。(這在概念上和EJB的interception相似,但實現得更簡單。) 

BeanFactories能在一個層次結構中選擇性地參與,繼承ancestor(祖先)的定義。這使得在整個應用中公共配置的共享成爲可能,雖然個別資源,如controller servlets,還擁有他們自己的獨立的對象集合。 

這種使用JavaBeans的動機在《Expert One-on-One J2EE Design and Development》的第四章中有描述,在TheServerSide網站上的有免費的PDF版本(http://www.theserverside.com/res ... RodJohnsonInterview)。 

通過BeanFactory概念,Spring成爲一個Inversion of Control的容器。(我不怎麼喜歡container這個詞,因爲它使人聯想到重量級容器,如EJB容器。Spring的BeanFactory是一個可通過一行代碼創建的容器,並且不需要特殊的部署步驟。) 

Inversion of Control背後的概念經常表述爲Hollywood原則的:“Don’t call me, I’ll call you。” IoC將控制創建的職責搬進了框架中,並把它從應用代碼脫離開來。涉及到配置的地方,意思是說在傳統的容器體系結構中,如EJB,一個組件可以調用容器並問“我需要它給我做工作的對象X在哪裏?”;使用IoC容器則只需指出組件需要X對象,在運行時容器會提供給它。容器是通過查看方法的參數表(例如JavaBean的屬性)做到的,也可能根據配置數據如XML。 

IoC有幾個重要的好處,例如: 



因爲組件不需要在運行時間尋找合作者,所以他們可以更簡單的編寫和維護。在Spring版的IoC裏,組件通過暴露JavaBean的setter方法表達他們依賴的其他組件。這相當於EJB通過JNDI來查找,EJB查找需要開發人員編寫代碼。 

同樣原因,應用代碼更容易測試。JavaBean屬性是簡單的,屬於Java核心的,並且是容易測試的:僅編寫一個自包含的Junit測試方法用來創建對象和設置相關屬性即可。 

一個好的IoC實現保留了強類型。如果你需要使用一個通用的factory來尋找合作者,你必須通過類型轉換將返回結果轉變爲想要的類型。這不是一個大不了的問題,但是不雅觀。使用IoC,你在你的代碼中表達了強類型依賴,框架將負責類型轉換。這意味着在框架配置應用時,類型不匹配將導致錯誤;在你的代碼中,你無需擔心類型轉換異常。 

大部分業務對象不依賴於IoC容器的APIs。這使得很容易使用遺留下來的代碼,且很容易的使用對象無論在容器內或不在容器內。例如,Spring用戶經常配置Jakarta Commons DBCP數據源爲一個Spring bean:不需要些任何定製代碼去做這件事。我們說一個IoC容器不是侵入性的:使用它並不會使你的代碼依賴於它的APIs。任何JavaBean在Spring bean factory中都能成爲一個組件。 


最後應該強調的是,IoC 不同於傳統的容器的體系結構,如EJB,應用代碼最小程度地依靠於容器。這意味着你的業務對象可以潛在的被運行在不同的IoC 框架上——或者在任何框架之外——不需要任何代碼的改動。 

以我和其他Spring用戶的經驗來說,再怎麼強調IoC給應用程序代碼帶來的好處也不爲過。 

IoC不是一個新概念,但是它在J2EE團體裏面剛剛到達黃金時間。 有一些可供選擇的IoC 容器: 例如 Apache Avalon, PicoContainer 和 HiveMind。Avalon 從沒怎麼流行,儘管它很強大而且有很長的歷史。Avalon相當的重和複雜,並且看起來比新的IoC解決方案更具侵入性。 PicoContainer是一個輕量級而且更強調通過構造函數表達依賴性而不是JavaBean 屬性。 與 Spring不同,它的設計允許每個類型一個對象的定義(可能是因爲它拒絕任何Java代碼外的元數據導致的侷限性)。在Spring, PicoContainer 和其他 IoC frameworks之間做比較,可參看文章Spring網站上的 "The Spring Framework - A Lightweight Container"位於http://www.springframework.org/docs/lightweight_container.html。這個頁面裏面包含了PicoContainer站點的鏈接 。 

Spring BeanFactories 是非常輕量級的。用戶已經成功地將他們應用在applets和單獨的Swing應用中。(它們也很好地工作在 EJB容器中。) 沒有特殊的部署步驟和察覺得到的啓動時間。這個能力表明一個容器在應用的任何層面幾乎立即可以發揮非常大的價值。

Spring BeanFactory 概念貫穿於Spring始終, 而且是Spring如此內在一致的關鍵原因。在IoC容器中,Spring也是唯一的,它使用IoC作爲基礎概念貫穿於整個功能豐富的框架。 

對應用開發人員,最重要的是,一個或多個BeanFactory提供了一個定義明確的業務對象層。這類似於local session bean層,但比它更簡單。與EJBs不同,在這個層中的對象可能是相關的,並且他們的關係被擁有它們的factory管理。有一個定義明確的業務對象層對於成功的體系結構是非常重要的。 

Spring ApplicationContext 是BeanFactory的子接口,爲下列東西提供支持: 



信息查找,支持着國際化 

事件機制,允許發佈應用對象以及可選的註冊以接收到事件 

可移植的文件和資源訪問 


XmlBeanFactory 例子 

Spring用戶通常在XML的“bean定義”文件中配置他們的應用。Spring的XML bean定義文檔的根是 元素。該元素包含一個或多個 定義。我們一般給每個bean定義的指定類和屬性。我們還必須指定ID作爲標識,這將成爲在代碼中使用該bean的名字。 

讓我們來看一個簡單的例子,它配置了三個應用程序對象,之間的關係在J2EE應用中常常能夠看到: 



J2EE DataSource 

使用DataSource的DAO 

在處理過程中使用DAO的業務對象 


在下面的例子中,我們使用一個來自Jakarta Commons DBCP項目的BasicDataSource。這個class(和其他許多已有的 class一樣)可以簡單地被應用在Spring bean factory中,只要它提供了JavaBean格式的配置。需要在shutdown時被調用的Close方法可通過Spring的"destroy-method"屬性被註冊,以避免BasicDataSource需要實現任何Spring 的接口。 

代碼: 


class="org.apache.commons.dbcp.BasicDataSource" 
destroy-method="close"> 
com.mysql.jdbc.Driver 
jdbc:mysql://localhost:3306/mydb 
root 


BasicDataSource中我們感興趣的所有屬性都是String類型的,因此我們用元素來指定他們的值。如果必要的話,Spring使用標準的 JavaBean屬性編輯器機制來把String轉換爲其他的類型。 

現在,我們定義DAO,它有一個對DataSource的bean引用。Bean間關係通過元素來指定: 

代碼: 
class="example.ExampleDataAccessObject"> 



The business object has a reference to the DAO, and an int property (exampleParam): 
class="example.ExampleBusinessObject"> 

10 




對象間的關係一般在配置中明確地設置,象這個例子一樣。我們認爲這樣做是件好事情。然而Spring還提供了我們稱做"autowire"的支持, 一個 la PicoContainer,其中它指出了bean間的依賴關係。這樣做的侷限性——PicoContainer也是如此——是如果有一個特殊類型的多個Bean,要確定那個類型所依賴的是哪個實例是不可能。好的方面是,不滿足的依賴可以在factory初始化後被捕獲到。(Spring 也爲顯式的配置提供了一種可選的依賴檢查,它可以完成這個目的) 

在上面的例子中,如果我們不想顯式的編寫他們的關係,可使用如下的autowire特性: 

代碼: 
class="example.ExampleBusinessObject" 
autowire="byType"> 

10 



使用這個特性,Spring會找出exampleBusinessObject的dataSource屬性應該被設置爲在當前BeanFactory中找到的DataSource實現。在當前的BeanFactory中,如果所需要類型的bean不存在或多於一個,將產生一個錯誤。我們依然要設置 exampleParam屬性,因爲它不是一個引用。 

Autowire支持和依賴檢查剛剛加入CVS並將在Spring 1.0 M2(到10/20,2003)中提供。本文中所討論的所有其他特性都包含在當前1.0 M1版本中。 

把管理從Java代碼中移出來比硬編碼有很大的好處,因爲這樣可以只改變XML文件而無需改變一行Java代碼。例如,我們可以簡單地改變 myDataSource的bean定義引用不同的bean class以使用別的連接池,或者一個用於測試的數據源。 XML節變成另一種,我們可以用 Spring的JNDI location FactoryBean從應用服務器獲取一個數據源。 

現在讓我們來看看例子中業務對象的java 代碼。注意下面列出的代碼中沒有對Spring的依賴。不像EJB容器,Spring BeanFactory不具有侵入性:在應用對象裏面你通常不需要對Spring的存在硬編碼。 

代碼: 
public class ExampleBusinessObject implements MyBusinessObject { 

private ExampleDataAccessObject dao; 
private int exampleParam; 

public void setDataAccessObject(ExampleDataAccessObject dao) { 
this.dao = dao; 


public void setExampleParam(int exampleParam) { 
this.exampleParam = exampleParam; 


public void myBusinessMethod() { 
// do stuff using dao 



注意那些property setter,它們對應於bean定義文檔中的XML引用。這些將在對象被使用之前由Spring調用。 

這些應用程序的bean不需要依賴於Spring:他們不需要實現任何Spring的接口或者繼承Spring的類。他們只需要遵守JavaBeans的命名習慣。在Spring 應用環境之外重用它們是非常簡單的,例如,在一個測試環境中。只需要用它們的缺省構造函數實例化它們,並且通過調用 setDataSource()和setExampleParam()手工設置它的屬性。如果你想以一行代碼支持程序化的創建,只要你有一個無參數的構造器,你就可以自由定義其他需要多個屬性的構造函數。 

注意在業務接口中沒有聲明將會一起使用的JavaBean屬性。 他們是一個實現細節。我們可以“插入”帶有不同bean屬性的不同的實現類而不影響連接着的對象或者調用的代碼。 

當然,Spring XML bean factories 有更多的功能沒有在這裏描述,但是,應當讓你對基本使用有了一些感覺。以及,簡單的屬性,有 JavaBean屬性編輯器的屬性,Spring可以自動處理lists,maps和java.util.Properties。 

Bean factories 和application contexts 通常和J2EE server定義的一個範圍相關聯,例如: 



Servlet context.:在spring 的MVC 框架裏, 每一個包含common objects的web 應用都定義有一個應用程序的 context。Spring提供了通過listener或者servlet實例化這樣的context的能力而不需要依賴於Spring 的MVC 框架,因而它也可以用於Struts,WebWork 或者其他的web框架之中。 

A Servlet:在Spring MVC 框架裏每一個servlet控制器都有它自己的應用程序context,派生於根(全應用程序範圍的)應用程序context。在Struts或者其他MVC框架中實現這些也很容意。 

EJB:Spring 爲EJB提供方便的超類,它們簡化了EJB的創建並且提供了一個從EJB Jar 文件中的XML文檔載入的BeanFactory。 


這些J2EE規範提供的hook通常避免了使用Singleton來創造一個bean factory。 

然而,如果我們願意的話可以用代碼創建一個BeanFactory,雖然是沒有什麼意義的。例如,我們在以下三行代碼中可以創建bean factory並且得到一個業務對象的引用: 

代碼: 
InputStream is = getClass().getResourceAsStream("myFile.xml"); 
XmlBeanFactory bf = new XmlBeanFactory(is); 
MyBusinessObject mbo = (MyBusinessObject) bf.getBean("exampleBusinessObject"); 



這段代碼將能工作在一個應用服務器之外:甚至不依賴J2EE,因爲Spring 的IoC容器是純java的。 

JDBC 抽象和數據存儲異常層次 

數據訪問是Spring 的另一個閃光點。 

JDBC 提供了還算不錯的數據庫抽象,但是需要用痛苦的API。這些問題包括: 



需要冗長的錯誤處理代碼來確保ResultSets,Statements以及(最重要的)Connections在使用後關閉。這意味着對JDBC的正確使用可以快速地導致大量的代碼量。它還是一個常見的錯誤來源。Connection leak可以在有負載的情況下快速宕掉應用程序。 

SQLException相對來說不能說明任何問題。JDBC不提供異常的層次,而是用拋出SQLException來響應所有的錯誤。找出到底哪裏出錯了——例如,問題是死鎖還是無效的SQL?——要去檢查SQLState或錯誤代碼。這意味着這些值在數據庫之間是變化的。 

Spring用兩種方法解決這些問題: 



提供API,把冗長乏味和容易出錯的異常處理從程序代碼移到框架之中。框架處理所有的異常處理;程序代碼能夠集中精力於編寫恰當的SQL和提取結果上。 

爲你本要處理SQLException程序代碼提供有意義的異常層次。當Spring第一次從數據源取得一個連接時,它檢查元數據以確定數據庫。它使用這些信息把SQLException映射爲自己從org.springframework.dao.DataAccessException派生下來的類層次中正確的異常。因而你的代碼可以與有意義的異常打交道,並且不需要爲私有的SQLState或者錯誤碼擔心。Spring的數據訪問異常不是JDBC特有的,因而你的DAO並不一定會因爲它們可能拋出的異常而綁死在JDBC上。 

Spring提供兩層JDBC API。第一個時,在org.springframework.jdbc.core包中,使用回調機制移動控制權——並且因而把錯誤處理和連接獲取和釋放——從程序的代碼移到了框架之中。這是一種不同的Inversion of Control,但是和用於配置管理的幾乎有同等重要的意義。 

Spring使用類似的回調機制關注其他包含特殊獲取和清理資源步驟的API,例如JDO(獲取和釋放是由PersistenceManager完成的),事務管理(使用JTA)和JNDI。Spring中完成這些回調的類被稱作template。 

例如,Spring的JdbcTemplate對象能夠用於執行SQL查詢並且在如下的列表中保存結果: 

代碼: 
JdbcTemplate template = new JdbcTemplate(dataSource); 
final List names = new LinkedList(); 
template.query("SELECT USER.NAME FROM USER", 
new RowCallbackHandler() { 
public void processRow(ResultSet rs) throws SQLException { 
names.add(rs.getString(1)); 

}); 


注意回調中的程序代碼是能夠自由拋出SQLException的:Spring將會捕捉到這些異常並且用自己的類層次重新拋出。程序的開發者可以選擇哪個異常,如果有的話,被捕捉然後處理。 

JdbcTemplate提供許多支持不同情景包括prepared statements和批量更新的方法。Spring的JDBC抽象有比起標準JDBC來說性能損失非常小,甚至在當應用中需要的結果集數量很大的時候。 

在org.springframework.jdbc.object包中是對JDBC的更高層次的抽象。這是建立在覈心的JDBC回調功能基礎紙上的,但是提供了一個能夠對RDBMS操作——無論是查詢,更新或者是存儲過程——使用Java對象來建模的API。這個API部分是受到JDO查詢API的影響,我發現它直觀而且非常有用。 

一個用於返回User對象的查詢對象可能是這樣的: 

代碼: 

class UserQuery extends MappingSqlQuery { 

public UserQuery(DataSource datasource) { 
super(datasource, "SELECT * FROM PUB_USER_ADDRESS WHERE USER_ID = ?"); 
declareParameter(new SqlParameter(Types.NUMERIC)); 
compile(); 


// Map a result set row to a Java object 
protected Object mapRow(ResultSet rs, int rownum) throws SQLException { 
User user = new User(); 
user.setId(rs.getLong("USER_ID")); 
user.setForename(rs.getString("FORENAME")); 
return user; 


public User findUser(long id) { 
// Use superclass convenience method to provide strong typing 
return (User) findObject(id); 




這個類可以在下面用上: 
代碼: 

User user = userQuery.findUser(25); 


這樣的對象經常可以用作DAO的inner class。它們是線程安全的,除非子類作了一些超出常規的事情。 

在org.springframework.jdbc.object包中另一個重要的類是StoredProcedure類。Spring讓存儲過程通過帶有一個業務方法的Java類進行代理。如果你喜歡的話,你可以定義一個存儲過程實現的接口,意味着你能夠把你的程序代碼從對存儲過程的依賴中完全解脫出來。 

Spring數據訪問異常層次是基於unchecked(運行時)exception的。在幾個工程中使用了Spring之後,我越來越確信這個決定是正確的。 

數據訪問異常一般是不可恢復的。例如,如果我們不能鏈接到數據庫,某個業務對象很有可能就不能完成要解決的問題了。一個可能的異常是 optimistic locking violation,但是不是所有的程序使用optimistic locking。強制編寫捕捉其無法有效處理的致命的異常通常是不好的。讓它們傳播到上層的handler,比如servlet或者EJB 容器通常更加合適。所有的Spring對象訪問異常都是 DataAccessException的子類,因而如果我們確實選擇了捕捉所有的Spring數據訪問異常,我們可以很容易做到這點。 

注意如果我們確實需要從unchecked數據訪問異常中恢復,我們仍然可以這麼做。我們可以編寫代碼僅僅處理可恢復的情況。例如,如果我們認爲只有optimistic locking violation是可恢復的,我們可以在Spring的DAO中如下這麼寫: 

代碼: 

try { 
// do work 

catch (OptimisticLockingFailureException ex) { 
// I'm interested in this 



如果Spring的數據訪問異常是checked的,我們需要編寫如下的代碼。注意我們還是可以選擇這麼寫: 
代碼: 

try { 
// do work 

catch (OptimisticLockingFailureException ex) { 
// I'm interested in this 

catch (DataAccessException ex) { 
// Fatal; just rethrow it 



第一個例子的潛在缺陷是——編譯器不能強制處理可能的可恢復的異常——這對於第二個也是如此。因爲我們被強制捕捉base exception (DataAccessException),編譯器不會強制對子類(OptimisticLockingFailureException)的檢查。因而編譯器可能強制我們編寫處理不可恢復問題的代碼,但是對於強制我們處理可恢復的問題並未有任何幫助。 

Spring對於數據訪問異常的unchecked使用和許多——可能是大多數——成功的持久化框架是一致的。(確實,它部分是受到JDO的影響。) JDBC是少數幾個使用checked exception的數據訪問API之一。例如TopLink和JDO大量使用 unchecked exception。Gavin King現在相信Hibernate也應該選擇使用unchecked exception。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章