領先一步
VMware 提供培訓和認證,以加速您的進度。
了解更多歡迎來到我的部落格! 這是我的第一篇文章...有史以來。 我設法抵擋了寫部落格的衝動,但由於很多人鼓勵我寫下我在 i21 所做的事情,所以我決定試試看。 加上 Spring-OSGi 昨天晚上(EET 時區)發布了第一個 版本。
我從去年八月開始參與 Spring-OSGi,這是一段相當長的旅程。 這是我做過最具挑戰性的專案之一,我很高興能夠將它作為一個里程碑發布給大眾。 非常感謝所有參與者促成此事,特別是我的 團隊 夥伴 - Adrian、Andy 和 Hal!
在這篇文章中,我想讓大家了解 Spring 1.0 M1 目前提供的功能;我將跳過 OSGi 的介紹,因為網路上有很多很棒的資料(請參閱底部的連結)。
Spring-OSGi 背後的基本想法是讓在 OSGi 環境中建構/編寫/部署 Spring 應用程式變得容易。 也就是說,讓 Spring 提供的全面性的 POJO 程式設計模型(IoC、AOP、服務抽象)在專注於版本控制和模組化的動態執行環境中透明地運作。
採用 OSGi 時最大的挑戰之一是處理其動態本質。 服務(它們是簡單的物件實例)來來去去,您的應用程式必須處理這個問題。 解決方案並非一蹴可幾,而是因案例而異,並且需要像異常處理和交易一樣的應用程式範圍。 模組化強制執行的類別載入限制,加上 AOP,可能會造成很多麻煩,並迫使開發人員建立駭客行為,從而拋棄 OSGi 提供的優勢。 這些僅僅是我們在 Spring-OSGi 中解決的少數範例,最終應該允許順利採用 OSGi。
讓我們看看您會在 1.0 M1 中找到的一些功能
OSGi 基於bundles,它們不過是一些具有專用 manifest 條目的 jars。 它們是模組,匯出和匯入類別套件和/或服務的單元。 一個應用程式可以由一個或多個 bundles 組成。 Spring-OSGi 提供了一個建立在 bundle 及其生命週期之上的應用程式上下文,讓您可以存取應用程式所在的 OSGi 上下文、一個 OSGi 自訂 範圍以及一個 額外 Aware 介面。 與其餘的類型一樣,該介面提供了執行依賴項查找的能力,在使用前您應該三思而後行,因為 OSGi 服務依賴項注入已完全受支援。
類別載入與 OSGi 中過去使用的不同 - 例如,類別路徑具有不同的含義,因為它可以從多個 bundles 組裝而成(這些 bundles 反過來可以用於多個類別路徑)。 因此,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 模式不具可攜性,因此 Spring OSGi 中完成的第一件事是透過簡單但有效的 Resource 介面封裝底層存取,因此無論您使用哪種 OSGi 實作,您都可以找到您的檔案。 此外,可以進行模式樣式查找,例如 myFolder/*(事實上,我們正在使用 /META-INF/spring/* 來偵測「spring powered」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 bundles 的絕佳候選者,因為人們可以簡單地將 DAO 類別放在一個 bundle(dao bundle)中,將服務層放在另一個 bundle(服務 bundle)中,因此當 DAO 實作更新時(例如,上面的poorPerformerDAO 被 excellentPerformerDAO 取代)或正在部署不同版本的應用程式時,不需要重新啟動應用程式:這是選擇 OSGi 的最佳理由之一!
但是,為了利用 OSGi 的功能,物件必須成為服務 - 也就是說,它們必須先在 OSGi 平台上註冊,然後才能被「使用」,而使用者(用戶端)必須尋找它們。 這是一種 SOA 類型的做法,可以避免模組之間的緊密耦合,因此當 bundle 關閉時,它發布的服務會消失。 這意味著人們必須首先使用 OSGi API 進行註冊和查找,但還必須處理失敗,因為服務可能會來來去去。
Spring-OSGi 在這方面提供了很大的幫助,它允許從字面上匯出和匯入應用程式中的任何類型的物件,而無需任何程式碼變更。
服務 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 中,然後只用 osgi:reference 取代直接的 ref。 沒有要處理的新 API,沒有要 try/catch/finally 的例外情況,並且特別內建查找行為。 可以指示 Spring-OSGi,除非找到實作 daoInterface 的服務 - 也就是說,可以滿足 dao 依賴項,否則應用程式上下文不會啟動。 此外,在執行階段,如果服務消失,Spring-OSGi 將根據您的配置(重試次數和逾時)自動尋找新的實作:如果在更新擁有 bundle 時(例如,將 goodPerformerDAO 升級到 excellentPerformerDAO),在 'dao' bean 上調用了呼叫,而不是得到一個令人討厭的、看似無法解釋的例外情況,而是會得到一個因新服務查找而導致的難以察覺的延遲。 與往常一樣,行為是完全配置的。
在某種程度上,匯出器/匯入器功能類似於 Spring remoting,但最大的區別是沒有涉及 remoting - 一切都在同一個 VM 中運行,並且沒有涉及序列化。
測試很重要(甚至至關重要),尤其是在將應用程式遷移到新環境時,因為很多理所當然的事情可能會失敗:我們在開發初期就親身體驗了這一點。 這一直是一個大問題,因為在談論 OSGi 時,測試並不容易或自動化,因為必須啟動(沒有標準化的 API)和設定(安裝您的測試所依賴的 bundles)執行環境(OSGi 平台或容器,如果您願意)。 然而,棘手的部分是測試本身必須進行 OSGi 化 - 與 manifest 放在一起,其中聲明了依賴項,放入必須安裝並啟動到 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(由我本人)最後,但同樣重要的是,good ol' Google。