OSGi框架-第一章- Equinox 框架中的相關知識點

MANIFEST.MF

MANIFEST.MF 可能出現在任何包括主類信息的 Jar 包中,一般位於 META-INF 目錄中,所以此文件並不是一個 OSGi 特有的東西,而僅僅是增加了一些屬性,這樣也正好保持了 OSGi 環境和普通 Java 環境的一致性,便於在老的系統中部署。表 2 列出此文件中的重要屬性及其含義:


表 2. MANIFEST.MF 文件屬性
屬性名字 含義
Bundle-Activator Bundle 的啓動器
Bundle-SymbolicName 名稱,一般使用類似於 JAVA 包路徑的名字命名
Bundle-Version 版本,注意不同版本的同名 bundle 可以同時上線部署
Export-Package 導出的 package 聲明,其它的 bundle 可以直接引用
Import-Package 導入的 package
Eclipse-LazyStart 是否只有當被引用了才啓動
Require-Bundle 全依賴的 bundle,不推薦
Bundle-ClassPath 本 bundle 的 class path,可以包含其它一些資源路徑
Bundle-RequiredExecutionEnvironment 本 bundle 必須的執行環境,例如 jdk 版本聲明

什麼是 bundle?

我們已經看到,編寫一個很普通的 Hello world 應用,必須首先創建一個 plug-in 工程,然後編輯其 Activator 類的 start 方法,實際我們這樣做的本質是爲 OSGi 運行環境添加了一個 bundle,那麼一個 bundle 必須的構成元素是哪些呢?

  1. MANIFEST.MF:描述了 bundle 的所有特徵,包括名字、輸出的類或者包,導入的類或者包,版本號等等,具體可以參考 表 2. MANIFEST.MF 文件屬性。
  2. 代碼:包括 Activator 類和其它一些接口以及實現,這個和普通的 Java 應用程序沒有什麼特殊的區別。
  3. 資源:當然,一個應用程序不可能沒有資源文件,比如圖片、properties 文件、XML 文件等等,這些資源可以隨 bundle 一起存在,也可以以 fragment bundle 的方式加入。
  4. 啓動級別的定義:可以在啓動前使用命令行參數指定,也可以在運行中指定,具體的 start level 的解釋,請參考 後面的說

框架做了些什麼?

好了,我們已經明白 bundle 是什麼了,也知道如何開發一個基本的 bundle 了,那麼我們還必須要明白,我的 bundle 放在 Equinox 框架中,它對我們的 bundle 做了些什麼?


圖 11. Equinox 框架架構
圖 11. equinox 框架架構 

實際上,目標平臺已經爲我們準備了 N 個 bundle,它們提供各種各樣的服務,OSGi 中,這些 bundle 的名字叫 system bundle,就好比精裝修的房子,您只需要拎包入住,不再需要自己鋪地板,裝吊頂了。

我們的 bundle 進入 Equinox 環境後,OSGi 框架對其做的事情如下:

  1. 讀入 bundle 的 headers 信息,即 MANIFEST.MF 文件;
  2. 裝載相關的類和資源;
  3. 解析依賴的包;
  4. 調用其 Activator 的 start 方法,啓動它;
  5. 爲其提供框架事件、服務事件等服務;
  6. 調用其 Activator 的 stop 方法,停止它;

Bundle 導入導出 package

OK,到現在爲止,似乎一切都是新鮮的,但是您似乎在考慮,OSGi 到底有什麼優勢,下面介紹一下其中的一個特點,幾乎所有的面向組件的框架都需要這一點來實現其目的: 面向服務、封裝實現 。這一點在普通的 Java 應用是很難做到的,所有的類都暴露在 classpath 中,人們可以隨意的查看您的實現,甚至變更您的實現。這一點,對於希望發佈組件的公司來說是致命的。


圖 13. OSGi bundle 原理
圖 13. OSGi bundle 原理 

OSGi 很好的解決了這個問題,就像上面的圖顯示的,每個 bundle 都可以有自己公共的部分和隱藏的部分,每個 bundle 也只能看見自己的公共部分、隱藏部分和其它 bundle 的公共部分。

bundle 的 MANIFEST.MF 文件提供了 EXPORT/IMPORT package 的關鍵字,這樣您可以僅僅 export 出您希望別人看到的包,而隱藏實現的包。並且您可以爲它們編上版本號,這樣可以同時發佈不同版本的包。

 

Bundle class path

這一點比較難理解,一般情況下您不需要關心這個事情,除非事情出現了問題,您發現明明這個類就在這裏,怎麼就是報告 ClassNotFoundException/NoClassDefExcpetion 呢?在您垂頭喪氣、準備砸掉電腦顯示器之前,請看一下 bundle 中的類是如何查找的:

  1. 首先,它會找 JRE,這個很明顯,這個實際是通過系統環境的 JAVA_HOME 中找到的,路徑一般是 JAVA_HOME/lib/rt.jar、tools.jar 和 ext 目錄,endorsed 目錄。
  2. 其次,它會找 system bundle 導出的包。
  3. 然後,它會找您的 import 的包,這個實際包含兩種:一種是直接通過 require-bundle 的方式全部導入的,還有一種就是前面講的通過 import package 方式導入的包。
  4. 查找它的 fragment bundle,如果有的話。
  5. 如果還沒有找到,則會找自己的 classpath 路徑(每個 bundle 都有自己的類路徑)。
  6. 最後它會嘗試根據 DynamicImport-Package 屬性查找的引用。 
發佈了80 篇原創文章 · 獲贊 54 · 訪問量 27萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章