領先一步
VMware 提供培訓和認證,助您加速進步。
瞭解更多歡迎來到我的部落格!這是我第一篇博文……有史以來第一篇。我一直抵制著寫部落格的衝動,但由於很多人鼓勵我寫我在i21所做的事情,我決定嘗試一下。再加上Spring-OSGi昨晚(東歐時間)釋出了第一個版本。
我從去年八月開始參與 Spring-OSGi 專案,這段經歷可謂跌宕起伏。這是我參與過的最具挑戰性的專案之一,我很高興它能釋出,哪怕只是一個里程碑,向公眾釋出。非常感謝所有參與其中的人,特別是我的 團隊 成員 - Adrian, Andy 和 Hal!
在這篇文章中,我想讓您一窺 Spring 1.0 M1 目前提供的功能;我將跳過對 OSGi 的介紹,因為網上有大量優秀的資料(請參見底部的連結)。
Spring-OSGi 的基本理念是簡化在 OSGi 環境中構建/編寫/部署 Spring 應用程式。也就是說,讓 Spring 提供的全面的 POJO 程式設計模型(IoC, AOP, 服務抽象)在一個以版本控制和模組化為重點的動態執行環境中無縫工作。
採用 OSGi 時最大的挑戰之一是處理其動態性。服務(它們只是簡單的物件例項)會來來往往,您的應用程式必須應對這種情況。解決方案並不直接,取決於具體情況,並且需要應用程式範圍的考量,就像異常處理和事務一樣。類載入限制,由前面提到的模組化強制執行,結合 AOP 可能會帶來很多麻煩,迫使開發者建立“ hacks”,從而將 OSGi 提供的優勢拋諸腦後。這些只是我們在 Spring-OSGi 中正在解決的 **一些** 問題的例子,最終應該能夠實現 OSGi 的平滑過渡。
讓我們來看一下 1.0 M1 中提供的一些功能
OSGi 基於 *bundles*,它們本質上就是帶有特定清單條目的 jar 檔案。它們是模組,是匯出和匯入類包和/或服務的單元。一個應用程式可以由一個或多個 bundle 組成。Spring-OSGi 提供了一個應用程式上下文,該上下文建立在 bundle 及其生命週期之上,讓您可以訪問應用程式所在的 OSGi 上下文,一個 OSGi 自定義 作用域以及一個 額外的 Aware 介面。像其他同類介面一樣,該介面提供了依賴查詢的功能,但您應該三思而後行,因為 OSGi 服務依賴注入是完全支援的。
在 OSGi 中,類載入不再像以前一樣了——例如,classpath 有了不同的含義,因為它可以從多個 bundle 中組合而成(這些 bundle 又可以用於一個以上的 classpath)。因此,getClass().getResource() 的結果可能會有所不同,因為您執行的環境已經發生了很大變化。下面是一個例子,說明您在查詢一個類時可能會得到什麼
Equinox: bundleentry://5/my/package/MyClass.class (也可能是 bundleresource://) Knopflerfish: bundle://13/my/package/MyClass.class Felix: bundle://18.0/0/my/package/MyClass.class
依賴 URL scheme 是不具有可移植性的,因此 Spring OSGi 做的第一件事就是透過簡單而有效的 Resource 介面封裝底層訪問,這樣無論您使用哪個 OSGi 實現,都可以找到您的檔案。此外,還可以進行模式匹配查詢,如 myFolder/*(實際上我們使用 /META-INF/spring/* 來檢測‘spring 驅動’的 bundles)。
假設您有以下應用程式上下文
<!-- service layer-->
<bean id="myService" class="ServiceClass">
<property name="dao" ref="dao"/>
</bean>
<!-- dao layer -->
<bean id="dao" class="poorPerformerDAO">
<property name="dataSource" ref="someDataSource"/>
</bean>
大多數應用程式都有幾個層次,它們是 OSGi bundle 的絕佳候選者,因為您可以簡單地將 DAO 類放在一個 bundle 中(dao bundle),將服務層放在另一個 bundle 中(service bundle),這樣當 DAO 實現更新時(例如,上面的 *poorPerformerDAO* 被 *excellentPerformerDAO* 替換)或者部署了應用程式的不同版本時,無需重新啟動應用程式:這是選擇 OSGi 的最好理由之一!
然而,要利用 OSGi 的能力,物件必須成為服務——也就是說,它們必須在被“消費”之前註冊到 OSGi 平臺,而消費者(客戶端)必須查詢它們。這是一種 SOA 式的方法,避免了模組之間的緊耦合,因此當一個 bundle 關閉時,它釋出的 خدمة 就會消失。這意味著您首先必須使用 OSGi API 進行註冊和查詢,同時還必須處理失敗,因為服務可能會出現也可能消失。
Spring-OSGi 在這方面提供了極大的幫助,它允許您在不更改任何程式碼的情況下匯出和匯入任何型別的物件。
Service Bundle
<!-- service layer-->
<bean id="myService" class="ServiceClass">
<property name="dao>
<osgi:reference interface="daoInterface"/>
</property>
</bean></code>
Dao Bundle
<!-- dao layer -->
<bean id="dao" class="goodPerformerDAO">
<property name="dataSource" ref="someDataSource"/>
</bean>
<osgi:service ref="dao"/>
使用 Spring-OSGi 來適應 OSGI 環境,需要新增兩行配置
<li><span style="font-family:courier"><osgi:service ..></span> to export an existing bean as an OSGi service</li>
顯然,對於 *dataSource* 依賴項也可以做同樣的事情——將其外部化到一個 OSGi bundle 中,然後將直接的 ref 替換為 osgi:reference。無需處理新的 API,無需 try/catch/finally 異常,尤其是內建的查詢行為。Spring-OSGi 可以被指示,直到找到一個實現 daoInterface 的服務,應用程式上下文才開始啟動——也就是說,dao 依賴項可以得到滿足。此外,在執行時,如果服務消失,Spring-OSGi 將根據您的配置(重試次數和超時時間)自動查詢新的實現:如果在服務所屬 bundle 更新時(例如,將 *goodPerformerDAO* 升級為 *excellentPerformerDAO*)呼叫了對 'dao' bean 的呼叫,您不會收到一個惱人的、看似無法解釋的異常,而是會因為新的服務查詢而產生一個微不可察的延遲。一如既往,該行為是完全可配置的。
在某種程度上,匯出器/匯入器功能類似於 Spring remoting,但有一個很大的區別,那就是沒有 remoting——一切都在同一個 VM 中執行,而且根本沒有序列化。
測試很重要(甚至至關重要),尤其是在將應用程式遷移到新環境時,因為很多理所當然的事情可能會失敗:我們在開發早期就親身經歷了這一點。這是一個大問題,因為在談論 OSGi 時,測試既不輕鬆也無法自動化,因為需要啟動(沒有標準化的 API)執行環境(OSGi 平臺或容器),並進行設定(安裝測試所需的 bundle)。然而,棘手之處在於測試本身必須是 OSGified 的——放在一個聲明瞭依賴關係的清單旁邊,放入一個必須安裝並啟動到 OSGi 平臺中的 bundle。
認識一下 AbstractOsgiTests & co
public class SimpleIntegrationTests extends AbstractConfigurableBundleCreatorTests
{
public void testInstalledBundles() {
// get access to the OSGi bundle context
Bundle[] bundles = getBundleContext().getBundles();
getBundleContext().installBundle(someBundleLocation);
assertEquals(bundles.length()+1, getBundleContext().getBundles().length());
}
// specify the bundles to install
protected String[] getBundles() {
return new String[] {
"org.springframework.osgi, commons-collections.osgi, 3.2-SNAPSHOT",
"org.springframework.osgi, org.springframework.osgi.test.simple.service,1.0-SNAPSHOT"};
}
}
AbstractOsgiTests 構建在 JUnit 之上,因此您可以直接從 IDE 中編寫和執行 OSGi 整合測試。整個設定由測試基礎設施處理,您無需這樣做:無需為您的測試編寫 MANIFEST.MF,無需進行任何打包或部署——一切都自動處理。而且它速度很快,非常快!實際上,啟動時間只有不到 10% 的時間花在 Spring-OSGi 程式碼內部——其餘時間由 OSGi 平臺本身使用。我們的大部分整合測試每個都完全在 1-3 秒內執行。Equinox、Knopflerfish 和 Felix 都得到了支援。
好了,我想第一篇文章的內容就夠了……我將在未來的文章中寫更多關於 Spring-OSGi 功能的內容。我希望我已經足夠引起您的好奇心,讓您嘗試一下 1.0 M1(請注意,這是第一個里程碑,還有一些‘粗糙的地方’)。
感謝閱讀!Costin
OSGi Alliance,它有一些不錯的 介紹 和 白皮書 Wikipedia EclipseCon OSGi 頻道 Spring-OSGi 規範 Javapolis 2006 關於 Spring-OSGi 的 簡報(由我自己主講)最後但同樣重要的是,老朋友 Google。