SpringSource 應用程式平台 Manifest 標頭

工程 | Glyn Normington | 2008 年 5 月 8 日 | ...

SpringSource 應用程式平台是由 OSGi 綁定 (bundles) 建構而成,並且支援同樣由 OSGi 綁定建構的應用程式。 此平台支援 OSGi 的標準功能,但也支援一些額外的 manifest 標頭。 許多人詢問 為什麼 SpringSource 要加入專有標頭? 以及 這些新標頭的語意是什麼?,因此這篇文章將解釋背景動機以及 Import-LibraryImport-Bundle 的語意。

標準 OSGi 綁定支援

此平台建立在 OSGi R4.1 標準之上,或如果您喜歡,也可以說是 JSR 291,並且使用 Equinox 作為其 OSGi 實作。 其結果是您可以使用此平台的工具開發標準 OSGi 綁定,並將這些綁定部署到平台上,許多使用者自此平台發布以來一直這麼做。

因此,精通 OSGi 的開發人員可以將此平台當作標準 OSGi 容器使用,並從平台功能中受益,例如:

  • 能夠使用管理主控台部署綁定,或將綁定放到平台的 pickup 目錄中,
  • 診斷功能,例如解析失敗診斷、應用程式特定的追蹤,以及自動死鎖偵測,
  • 與 Spring 和 Spring Dynamic Modules 強力整合,供想要使用這些框架的開發人員使用,以及
  • 從儲存庫自動佈建相依性。
然而,此平台也旨在讓對 OSGi 沒有事先經驗的企業應用程式開發人員更容易從 OSGi 中受益,這對平台提出了一些額外的要求。

企業應用程式的額外要求

如同 Sam 最近關於平台部署選項的 部落格 所解釋的,您可以在平台上部署現有的單體 WAR 檔案,而無需了解 OSGi - 平台會為您處理一切。 但要從共用函式庫、共用服務以及最終的 PAR 檔案範圍劃定中受益,就必須將單體 WAR 檔案拆解成 OSGi 綁定。 這有多難呢?

嗯,此過程中的某些步驟相對容易,特別是如果遵循了良好的軟體工程實務,並且將程式碼組織成服務、網域和基礎架構元件。 這些元件可以轉換為綁定,並且它們之間的相依性可以使用標準 OSGi Import-Package 和 Export-Package 標頭在 META-INF/MANIFEST.MF 中表示。

一個比較困難的步驟是表示對企業框架 (例如 Spring 和 Hibernate) 的相依性。 完全可以使用標準 OSGi Import-Package 和 Require-Bundle 標頭來表示這些相依性,如果您想建立可在其他 OSGi 容器中執行的 OSGi 綁定,這正是您應該做的事情,但這種方法有一些隱藏的成本。

首先,開發人員必須準確地決定哪些套件 (packages) 組成給定的框架。 僅匯入應用程式程式碼使用的套件是不夠的,因為當應用程式載入時,一些企業框架會將進一步的相依性織入 (weave) 應用程式的位元碼中。 開發人員必須發現 (可能透過試誤法) 要匯入哪些額外的實作套件,以確保織入應用程式的行為正確。

然後,如果組成框架的確切套件組發生變更,就必須進行從一個框架版本遷移到下一個版本的繁瑣工作。 織入所需的額外套件通常不由公開合約定義,因此可能會發生變更。

此外,產生的套件匯入無法正確捕捉設計意圖,這使得將來維護或擴展應用程式更加困難。

我們真的不想將這些負擔強加給我們的使用者,因此我們建立了一些額外的 SpringSource 應用程式平台特定 manifest 標頭 Import-LibraryImport-Bundle,作為表示對企業框架相依性的便捷方式。 正如下面您將看到的,這些標頭實際上只是 語法糖,以標準 OSGi 套件匯入來表示。

Import-Library

基本語法與其他 manifest 標頭的語法相似
    Import-Library: <librarySymbolicName>;version=<versionRange>
其中 <librarySymbolicName> 是函式庫的 符號名稱,而 <versionRange> 是使用 OSGi 版本範圍表示法之可接受函式庫版本的範圍。 函式庫定義指定了函式庫的符號名稱和版本,這些名稱和版本一起唯一地識別平台上的函式庫。

如果您不熟悉 OSGi 版本範圍表示法,到目前為止最常用的形式是最小版本範圍,例如 2,表示 2 版或更高版本,以及 半開 範圍,例如 [2.2.1,2.2.2),表示 2.2.1 (含) 和 2.2.2 (不含) 之間的任何版本。 如果省略了 version=<versionRange> 以及分號分隔符號,則預設範圍包含所有版本。

對於每個函式庫匯入,平台會選取具有給定符號名稱以及平台儲存庫中給定版本範圍內最高版本的函式庫。 然後,平台會將函式庫匯入替換為一組與函式庫綁定所匯出的所有套件相符的套件匯入。 平台會偵測到綁定匯入兩個或多個匯出通用套件的函式庫的情況,發布適當的日誌訊息,並且無法安裝匯入綁定。

因此,舉例來說,以下標頭匯入了 2.5.4 (含) 和 2.5.5 (不含) 之間的某個版本的 Spring Framework 函式庫

    Import-Library: org.springframework.spring;version="[2.5.4,2.5.5)"

選擇性函式庫匯入

您可以使用以下語法指出函式庫匯入是選擇性的。 請注意特殊的分隔符號 :=,它指示修改 manifest 標頭語意的 指令,而不是指示 比對屬性 的分隔符號 =,例如 version
    Import-Library: <librarySymbolicName>;version=<versionRange>;resolution:=optional

如果未指定 resolution,或指定為 mandatory,則如果沒有具有給定符號名稱且版本在給定範圍內的函式庫,則包含匯入函式庫標頭的綁定將無法安裝。 但是,如果指定了 resolution:=optional,則如果沒有合適的函式庫可用,則將忽略函式庫匯入。

因此,舉例來說,以下標頭匯入了從 2.5 開始的某個版本的 Spring Framework 函式庫,但如果沒有合適的函式庫可用,則會忽略它

    Import-Library: org.springframework.spring;version="2.5";resolution:=optional

匯入多個函式庫

如果您需要匯入多個函式庫,請在單個 Import-Library manifest 標頭中指定以逗號分隔的函式庫匯入清單,如以下範例所示
    Import-Library: org.foo.p;version="[1,2)",org.bar.q;version="[2,3)"

Import-Bundle

對於函式庫僅由單個綁定組成,並且建立函式庫定義很不方便的情況,Import-Bundle 是一個更方便的選擇。 其語法與 Import-Library 非常相似,只不過它引用的是綁定的符號名稱和版本,而不是函式庫的符號名稱和版本。

正如您所預期的,對於每個匯入的綁定,平台會選取具有給定符號名稱以及平台儲存庫中給定版本範圍內最高版本的綁定。 然後,平台會將綁定匯入替換為一組與綁定所匯出的套件相符的套件匯入。

因此,舉例來說,以下標頭匯入了 Hibernate 物件關聯對應器綁定

    Import-Bundle: com.springsource.org.hibernate;version="[3.2.6,3.2.7)"

為什麼不超載 Require-Bundle

如果您熟悉 OSGi,您可能會問自己,為什麼我們不超載 Require-Bundle,而是引入 Import-Bundle

嗯,我們希望 Require-Bundle 保留其標準語意,包括將分割套件的各部分組合在一起的能力。 但我們希望 Import-LibraryImport-Bundle 具有與 Import-Package 相同的底層語意,這避免了分割套件的複雜性。

我們也預期,隨著平台隨著時間的推移而不斷發展,我們需要向 Import-LibraryImport-Bundle 添加更多指令,而這不適合添加到 Require-Bundle

下一步是什麼?

平台 beta 計劃 正在進行中,我們將傾聽所有關於平台功能的意見反應,包括新的 manifest 標頭。

對於想要利用平台標頭,但需要產生可在其他 OSGi 容器上執行的綁定的使用者,我們計劃製作一個工具,將 Import-LibraryImport-Bundle 語法糖替換為等效的標準套件匯入。

我們還將與 OSGi 聯盟的同事討論新的 manifest 標頭,以確定是否存在一般要求,適合 OSGi 在將來解決。

取得 Spring 電子報

透過 Spring 電子報保持聯繫

訂閱

取得領先

VMware 提供培訓和認證,以加速您的進展。

了解更多

取得支援

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

了解更多

即將舉行的活動

查看 Spring 社群中所有即將舉行的活動。

查看全部