回應:EJB 3 和 Spring 對比分析

工程 | Mark Fisher | 2007年11月9日 | ...

昨晚我參加了新英格蘭 Java 使用者組(NEJUG)的一次會議,Reza Rahman 在會上展示了關於EJB 3 和 Spring 的“對比分析”。Reza 是《EJB 3 in Action》的作者之一。我很高興見到 Reza,也很敬佩他能就一個可能引起爭議的話題進行演示。我也很讚賞他嘗試分析 EJB 3 和 Spring 的優缺點。然而,我感到有必要澄清一些他對 Spring 的介紹中並非完全準確的觀點,這些觀點讓我(以及其他與會者)認為本次演示帶有偏向 EJB 3 的傾向。公平地說,與固定規範版本不同,Spring 正在不斷發展,我在這裡指出的一些內容是新特性。另一方面,有些是 Spring 2.0 的特性,已經存在一年多了。我個人認為,“對比分析”必須考慮所比較產品最新穩定版本的最新特性集。我想不言而喻的是,我也可能有一點偏見,但我在這裡的動機是提供一個完全客觀的回應,以便簡報可以修改,以反映更“同類相比”的比較。我將對簡報的 10 個“主題”提供簡要回應。

1. EJB 使用註解表示元資料。Spring 使用 XML。

演示中提到,Spring 開始支援更多註解,但“還需要一段時間”。然而,Spring 2.0 版本提供了完整的 JPA 整合,使用 @PersistenceContext 注入 EntityManager,並支援基於註解的事務管理,使用 Spring 的 @Transactional 註解(支援與預設傳播 REQUIRED 的 @Stateless EJB 相同的語義)。特別讓我沮喪的是,本次比較沒有在雙方都包含 JPA(參見下面的第 3 點)。Spring 2.0 還引入了完整的基於註解的 AspectJ 支援(@Aspect、@Before、@After、@Around)和“stereotype”註解的概念。例如,@Repository 註解為直接使用 JPA 或 Hibernate API 的資料訪問程式碼(不使用 Spring 模板)提供了非侵入式的異常轉換功能。Spring 甚至早在 1.2 版本就提供了註解支援,例如 @ManagedResource,用於透明地將任何 Spring 管理的物件匯出為 JMX MBean。

對我來說,這個問題成為第一位的主要原因是演示中提到“還需要一段時間”。作為 Spring 2.5 基於註解的配置支援的主要開發者之一,我必須說 Spring 的元資料模型極其靈活,因此我們能夠比預期更快地提供一個全面的基於註解的模型。事實上,Spring 2.5 支援 JSR-250 註解:@Resource、@PostConstruct 和 @PreDestroy,以及 @WebServiceRef 和 @EJB。特別值得關注的是 @Resource,因為它是 EJB 3 中用於依賴注入的主要註解。在 Spring 中,@Resource 註解不僅支援 JNDI 查詢(與 EJB 3 一樣),還支援注入任何 Spring 管理的物件。這有效地將演示中提到的 Spring 主要優勢(Spring 支援注入任何型別的物件)與 EJB 3 主要優勢(使用註解而非 XML)結合起來。Spring 2.5 還引入了一種更細粒度的基於註解的依賴注入模型,該模型基於 @Autowired 和(可擴充套件的)@Qualifier 註解。Spring 2.5 還將“stereotype”註解擴充套件到包括 @Service 和 @Controller。每個 stereotype 註解透過將其作為元註解應用來擴充套件通用的 @Component 註解。透過應用相同的技術,@Component 註解為使用者定義的 stereotypes 提供了一個擴充套件點。Spring 甚至可以自動檢測這些帶註解的元件,作為 XML 配置的替代方案。例如,以下摘錄來自 PetClinic 示例應用的 2.5 版本:


   <context:component-scan base-package="org.springframework.samples.petclinic.web" />

對於 web 控制器來說,不需要額外的 XML 配置,因為它們使用了基於註解的依賴注入和請求對映註解。我之所以指出這一點,是因為演示特別強調了 web 層配置的冗長性。


@Controller
public class ClinicController {

   private final Clinic clinic;

   @Autowired
   public ClinicController(Clinic clinic) {
      this.clinic = clinic;
   }
   ...

要獲取 Spring 註解支援的最新資訊,請參閱:The Server Side 上的 Spring 2.5 介紹,或 Spring 參考手冊的最新版本——特別是基於註解的配置部分。另外,請繼續關注本部落格和Spring Framework 主頁,我們將很快釋出一些關於 2.5 版本的文章和部落格。

2. Spring 允許您支援多種部署環境,但需要更多配置。

這一點實際上被作為 Spring 的一個優點提出,但強調了配置開銷。事實是,任何認真對待測試和敏捷開發的專案都需要支援“多種部署環境”。換句話說,這個話題常常被扭曲,彷彿只適用於多個生產環境。實際上,在每個開發和測試周期都必須部署到應用伺服器,這是敏捷性的主要障礙。通常,Spring 使用者會將配置模組化,以便“基礎設施”配置(例如 DataSource、TransactionManager、JMS ConnectionFactory)是分開的,並且動態屬性是外部化的。由於 Spring 支援根據外部化屬性替換 '${placeholders}',因此包含不同的屬性檔案通常會成為一個透明的問題。

3. EJB 使用 JPA,Spring 使用 Hibernate

我必須承認這一點最讓我困擾。在對比幻燈片中,EJB 3 的示例展示了透過 entityManager 進行資料訪問的 JPA,並且 entityManager 例項是透過 @PersistenceContext 註解提供的。另一方面,Spring 的示例使用了 Hibernate,並展示了 Hibernate SessionFactory 的 setter 注入。在我看來,這違反了真正的“對比分析”的第一條規則:在比較的雙方使用最相似的功能。在這個特定的案例中,Spring 確實支援直接使用 JPA API(例如,JpaTemplate 是完全可選的;直接使用 'entityManager' 仍然參與 Spring 事務等),並且 Spring 也識別 @PersistenceContext 註解。這項支援自 Spring 2.0 版本以來就已提供(最終版本釋出於一年多前),所以我不知道為什麼比較中沒有在 Spring 側也使用 JPA。比較的其他部分顯然是基於 Spring 2.0 的,因此這給人的印象是選擇性地過時並暴露了偏見。如果這個特定的例子被修改為“同類相比”,它就會破壞一個主要的主題:即 Spring 需要更多配置而 EJB 3 依賴標準註解。

現在,即使我認為在 Spring 側使用 Hibernate 而不是 JPA 扭曲了比較,它同時也揭示了 Spring 的一個優勢。如果您確實想直接使用 Hibernate API 而不是依賴 JPA API,Spring 支援這樣做,並且在 Spring 事務管理和異常轉換方面以一致的方式進行。這為使用超出 JPA 限制的 Hibernate 特性提供了機會,例如 Hibernate 的“criteria”查詢 API。同樣地,如果您想在 ORM 過於繁重的地方新增一些直接的 JDBC 進行資料訪問,Spring 也支援這樣做——即使在與 Hibernate 或 JPA 資料訪問相同的事務中呼叫。

4. Spring 不做任何假設,您必須提供配置。

一個具體的例子是事務管理器的定義。演示中提到,您必須瞭解容器供應商級別的細節才能配置 Spring 整合。這是不正確的。例如,以下 bean 定義不包含任何容器特定的資訊,但 Spring 將在所有 Java EE 應用伺服器中自動檢測事務管理器:


   <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>

如果您確實想利用容器特定功能,例如按事務隔離級別,那麼 Spring 也提供了一些專門的實現:WebLogicJtaTransactionManagerWebSphereUowTransactionManagerOC4JJtaTransactionManager。在這些實現之間切換隻需更改這個單一的定義即可。

此外,Spring 配置的幻燈片過於冗長。我擔心這可能也是為了強調 EJB 不同於 Spring,它依賴智慧預設設定的目標所驅動的。例如,幻燈片顯示:


   <tx:annotation-driven transaction-manager="transactionManager"/>

實際上,如果在 Spring 上下文內定義了單個 'transactionManager',那麼 'annotation-driven' 元素上就不需要顯式提供該屬性。該屬性僅用於在同一個應用中如有必要啟用使用多個事務管理器。這些“自動檢測”和“智慧預設”技術貫穿於 Spring 中,例如用於訊息監聽器的 JMS 'connectionFactory'(在下面的第 6 點示例中是隱含的)以及自動定位現有的 MBean 伺服器或 RMI 登錄檔。

從積極的方面看,演示中確實將 Spring 允許“本地”事務管理作為一個優點提到。雖然 EJB 需要 JTA 進行事務管理,但許多應用不需要跨支援兩階段提交的資源的分散式事務。在這種情況下,Spring 允許使用開銷更小的更簡單的事務管理器:DataSourceTransactionManager(用於 JDBC)、HibernateTransactionManager 或 JpaTransactionManager。如果目標是準確描述優缺點,我本期望聽到更多關於這個特定 Spring 優勢的細節。例如,這對於在容器外部進行測試或在 Eclipse 或 IDEA 等輕量級 IDE 環境中進行開發是一個巨大的好處。

此外,如果您確實需要 JTA 進行分散式事務,但想在 Tomcat 或 Jetty 等輕量級容器中執行,Spring 輕鬆支援獨立的 JTA 提供商,如 Atomikos 和 JOTM。誠然,Spring 的事務管理器設定需要配置一個單一的 bean 定義,但這確實是一次性的開銷——而且非常值得。

5. Spring 沒有有狀態的應用正規化。

無狀態服務層的好處作為最佳實踐已經相當成熟,Spring 也接受這一點。然而,Spring 確實提供了除 singleton 之外的其他作用域。Spring 的“prototype”作用域為每次注入或查詢提供一個不同的例項,Spring 2.0 引入了 web 作用域:“request”和“session”。作用域機制本身甚至是可以擴充套件的;可以將自定義作用域定義並對映到會話概念。Spring 也支援使用 CommonsPoolTargetSource 進行簡單的物件池化,但物件池化很少是狀態管理的最佳解決方案。

更重要的是,Spring 透過 Spring Web Flow 為 Web 應用提供了非常健壯、高度可配置的狀態管理功能。在那裡,會話狀態是透明管理的,這與本次演示中聲稱開發者必須直接與 HTTP Session 互動來管理 Spring 應用中的狀態的說法是矛盾的。此外,儲存庫配置是可插拔的,因此可以使用各種策略來物理儲存狀態(會話、客戶端、後端快取等)。最後,Spring Web Flow 的最新進展包括對擴充套件持久化上下文的支援以及對 JSF 的完全整合支援。

6. Spring 需要為每個 MessageListener 配置一個容器。

Spring 2.5 提供了一個新的 'jms' 名稱空間,極大地簡化了訊息監聽器的配置。請注意,不需要為每個監聽器單獨配置一個容器。多個監聽器共享配置,並且廣泛使用了智慧預設設定:


<jms:listener-container>
	<jms:listener destination="queue.confirm" ref="logger" method="log"/>
	<jms:listener destination="queue.order…

下載《Spring 在生產環境中的應用》白皮書

工程 | Adrian Colyer | 2007年11月9日 | ...

我們最近舉辦了一個主題為“Spring 在生產環境中的應用”的網路研討會。當時我承諾將網路研討會的錄音和配套幻燈片放在我們的網站上。不幸的是,為我們製作網路研討會的工程師忘記設定“錄製”標誌,所以我需要為您重新錄製會話 :(。我現在正在旅途中,但我會盡快嘗試完成並使其可用。

好訊息是,與此同時您不必錯過。我撰寫了一篇關於“Spring 在生產環境中的應用”的白皮書,涵蓋了網路研討會的內容以及更多…

Spring Java 配置向前發展

工程 | Rod Johnson | 2007年11月5日 | ...

一些使用者詢問我們是否致力於 Spring Java 配置,以及它與 Spring 2.5 中引入的註解配置選項如何共存。答案是肯定的,我們致力於 Java 配置;這兩種方法並非相互排斥。

這兩種配置方法截然不同:Spring Framework 中的 @Autowired 註解使用業務物件中的註解配置元件,而 Spring Java Config 採用了一種獨特的方法,將註解外部化到專門的配置類中。這兩種方法都沒有絕對的對錯…

Spring 2.5 RC1 釋出 - 引入新的配置方法

工程 | Juergen Hoeller | 2007年10月24日 | ...

正如 你們中一些人已經注意到的那樣,Spring 2.5 RC1 已於週一釋出,正等著您進行測試!在很多方面,Spring 2.5 是一個完成 Spring 2.0 使命的版本:為 Java 1.4 和 Java 5 提供最靈活、最全面的配置模型。Spring 2.5 專注於對 Java 5 的特別全面的支援,引入了各種進一步的註解選項。我想借此機會指出本次版本背後的統一主題

Spring 2.5 允許方便的外部化配置,同時保持其儘可能簡潔。這建立在 Spring 2.0 對 XML Schema 名稱空間的支援之上,Spring 2.5 引入了新的“context”和“jms”配置名稱空間。後者是 Spring 配置名稱空間可以提供的增值的一個特別好的例子——如果您正在使用 Spring 2.0 風格的訊息驅動物件,絕對值得采用!此外,Spring 也允許不涉及 XML 的程式設計方式啟動

Spring 工具套件

工程 | Adrian Colyer | 2007年10月16日 | ...

您可能已經看到了關於 Interface21 與 Tasktop 合作建立“Spring 工具套件”的宣佈一些近期新聞報道。該套件將整合 Spring IDEAspectJ 開發工具 (AJDT)AspectJMylyn,以建立一種以任務為中心的方法來開發基於 Spring 的企業應用。我們希望在即將到來的 The Spring Experience 會議上提供整合套件的預覽版供您分享,但與此同時,您將看到許多改進正在融入現有的 Spring IDE、AJDT、AspectJ 和 Mylyn 開源專案…

Gartner 精闢分析創新與顛覆

工程 | Neelan Choksi | 2007年10月12日 | ...

在上個月的 Gartner 開源大會上,分析師宣稱開源已經滲透到全球軟體市場的很大一部分。詳細資訊在最近的 Matt Asay 部落格中得到了強調,該部落格引用了eWeek 文章。eWeek 寫道:“開源產品在 2006 年佔據了 927 億美元軟體市場份額的 13%,但預計到 2011 年,當收入預計達到 1692 億美元時,將佔據市場份額的 27%。”

與此同時,Gartner 分析師 Massimo Pezzini 和 Yefim Natis 發表了一份報告,強調了當前正在進行的中介軟體和事務處理市場中的一個重要顛覆性趨勢。這份 2007 年 9 月 24 日釋出的報告,題為“平臺中介軟體趨勢:顛覆在望,”,強調了十多個“將顛覆看似靜態的應用伺服器和事務處理市場”的趨勢,並警告說…

我們對 JCP 的態度

工程 | Rod Johnson | 2007年9月30日 | ...

正如我之前釋出的,Interface21 正在參與 Java EE 6 的工作,包括我在內的 Juergen Hoeller、Keith Donald 和 Rob Harrop 等多人將參與多個專家組。

這意味著我們總體上更多地參與了 JCP。我們尊重 JCP 的保密規定及其他條款,因此不會談論任何非公開內容。然而,我想談談我們參與 JCP 的目標以及我們將帶來的基本方法。當然,我們只是眾多公司和個人中的一員,所以我們只是…

新的 bean() 切點

工程 | Ramnivas Laddad | 2007年9月24日 | ...

Spring 2.5 提供了一個新的切點指示符 -- bean(),它允許選擇與名稱模式匹配的 bean 中的連線點。現在可以使用自動代理機制結合 Spring-AspectJ 整合來選擇特定的 bean,即使同類型存在多個 bean。之前,您可以使用 BeanNameAutoProxyCreator 實現類似的結果;然而,該機制不適用於 Schema 風格或 @AspectJ 切面。

除了選擇特定的 bean 外,如果您遵循適當的命名約定,此切點指示符還提供了兩種有趣的方式來選擇 bean:

  1. 選擇 bean 的垂直切片:如果您遵循一個約定,即 bean 名稱包含一個表示其業務角色的字串,則 bean() 切點可以根據其業務角色選擇 bean。例如,如果 bean 名稱以表示其業務功能的字串開頭,您可以使用 bean(account*) 切點來選擇所有與會計相關的 bean,例如 accountRepositoryaccountServiceaccountController
  2. 選擇 bean 的水平切片:如果您遵循一個約定,即 bean 名稱包含一個表示其架構角色的字串,則 bean() 切點可以根據其架構角色選擇 bean。例如,如果 bean 名稱以表示其架構角色的字串結尾,您可以使用 bean(*Repository) 來選擇所有儲存庫 bean。如果沒有 bean() 切點,您必須依賴於包結構或基於型別的切點,這有時可能會過於嚴格。
The bean() Pointcut Designator

圖 1:使用 bean() 切點根據 bean 名稱選擇水平和垂直切片

此切點代表了 AspectJ 切點表示式語言的一個 Spring 特定擴充套件,因此僅在基於 Spring 的應用中有用。名稱模式遵循 AspectJ 對名稱模式的匹配規則,其中 '*' 是唯一允許的萬用字元。下表展示了一些示例切點及其選擇的 bean:
切點 選擇的連線點
bean(accountRepository) 名稱為 "accountRepository" 的 bean
!bean(accountRepository) 除 "accountRepository" bean 外的任何 bean
bean(*) 任何 bean
bean(account*) 名稱以 "account" 開頭的任何 bean
bean(*Repository) 名稱以 "Repository" 結尾的任何 bean
bean(accounting/showaccount) 名稱為 accounting/showaccount 的 bean(例如,指定處理該 URL 的控制器)
bean(accounting/*) 名稱以 "accounting/" 開頭的任何 bean(例如,指定處理會計相關 URL 的任何控制器)
bean(accounting/*/edit) 名稱以 "accounting/" 開頭並以 "/edit" 結尾的任何 bean(例如,指定處理與會計相關的編輯操作功能的任何控制器)
bean(*dataSource) || bean(*DataSource) 名稱以 "dataSource" 或 "DataSource" 結尾的任何 bean
bean(service:name=monitoring) 名稱為 "service:name=monitoring" 的 bean

關於開源的更多廢話

工程 | Rod Johnson | 2007年9月22日 | ...

在一篇標題貼切的 關於 Interface21 的廢話 文章中,SourceLabs 的一名員工不同意我的論點,即提交許可權對於提供可信的開源支援是必需的。

在我回應之前:我想再次完全明確一些我已經在上篇部落格中說過、但似乎被一些人誤解的事情:Interface21 無意阻止其他人從 Spring 中賺錢。我們的過往記錄證明了這一點。我們歡迎其他人撰寫關於 Spring 的文章並提供 Spring 服務。或者基於 Spring 開發產品,例如 Matt Raible 的 AppFuse。我們祝願他們成功。Spring 之所以能有今天的成就,部分歸因於…

回應關於開源的廢話

工程 | Rod Johnson | 2007年9月20日 | ...

我幾個月前寫的關於開源商業模式的部落格似乎引起了共鳴。我收到了許多積極回應,並因此接到了一個名為“軟體如何構建”的網站的採訪請求。我的採訪在這裡

最後,OpenLogic 的某人發表了一篇有趣的回應。Bryan Noll 在對我部落格的回應中留下了一些評論,值得認真回應。

首先,我認為您提出的論點,即當對特定專案沒有實際投入的人為其提供支援時,這對專案或整個開源生態是不健康的,這是個有趣的觀點……我之前從未聽過。我認為這個論點有足夠的合理性,足以讓像我們這樣的公司認真考慮,並真正審視我們對所支援的開源專案的責任。在我看來,這次審視的結果將是 OpenLogic 為緩解您提出的潛在顧慮而採取的一項可證明的政策。我確定我不知道具體會是什麼,所以請允許我在此刻保持模糊。然而,這一點與我對您所說的一些問題非常契合。
我認為找到這樣一項“可證明的政策”是相當簡單的。OpenLogic 需要理解 Stormy 的帖子中的開篇評論“在開源軟體上工作的開發者通常有不錯收入的全職工作……所以他們在空閒時間免費為開源軟體工作,白天則為了豐厚報酬寫程式碼”在很大程度上是錯誤的,他們需要理解他們希望從中獲利的開源軟體來自何處,恰當地建立夥伴關係,並設定一個允許提供真正支援的價格點。另一種選擇是停止聲稱提供企業級支援,並明確所提供的只是某種隨叫隨到的開發協助,不能保證能夠解決關鍵問題。這又回到了為什麼我對 Stormy 的帖子有強烈感受並對其進行解構的原因。

我將聚合模型視為超市模式的業務。當我在超市購物時,我期望他們從我購買的所有商品中抽取(少量)提成,以換取他們處理眾多供應商,並將所有商品彙集…

獲取 Spring 新聞郵件

訂閱 Spring 新聞郵件,保持聯絡

訂閱

領先一步

VMware 提供培訓和認證,助力您的進步。

瞭解更多

獲取支援

Tanzu Spring 在一項簡單的訂閱中提供對 OpenJDK™、Spring 和 Apache Tomcat® 的支援和二進位制檔案。

瞭解更多

近期活動

檢視 Spring 社群的所有近期活動。

檢視全部