HelloWorld
一般情況下,學習一門新的技術,程序員都習慣於首先開發一個 hello world 應用程序,這似乎也是一種“工業標准”。好的,讓我們開始吧,開發一個簡單的 OSGi 應用程序並不難,步驟如下:
- 建立一個 plug-in 工程,File > New > Project,選擇 Plug-in development > Plug-in Project
圖 1. 新建 plug-in 工程 - 在建立工程的第一個向導,填入工程的名稱:
osgi.test.helloworld
,使用缺省的工程路徑。注意目標平台的選擇,由於我們的項目是一個通用的 OSGi bundle,所以選擇 equinox 。
圖 2. 填入工程名及選擇目標平台 - 在下一個向導界面中,填入需要的一些插件信息(注意 Eclipse 中的插件概念基本類似於 OSGi 中的 bundle 的概念),這里需要填入的是 OSGi 的 provider(供應商)和 classpath 。如果沒有特別的設計,一般可以忽略這兩個字段 。最后是關於 activator 的部分,如果不是一個 fragment bundle 則需要填入,除非您的 bundle 自己實現框架的事件監聽,這個似乎也沒有必要。因此,建議使用缺省的設置,如圖 3:
圖 3. 使用缺省設置
Activator:這是 bundle 啟動時首先調用的程序入口,相當於 Java 模塊中的 main 函數。不同的是,main 需要通過命令行調用,而 OSGi 的 Activator 是被動的接受 OSGi 框架的調用,收到消息后才開始啟動。
最佳實踐:不要在 Activator 中寫太多的啟動代碼,否則會影響 bundle 啟動速度,相關的服務啟動可以放到服務的監聽器中。
- 最后一步,不使用任何的模板,所以勾掉缺省的選項,點擊完成,如圖 4:
圖 4. 勾掉缺省的選項 - 完成,基本的插件視圖如圖 5,Eclipse 會在工程名下建立相同路徑的 Java Package,其中包含了 Activator 類,插件的配置信息也都放在 MANIFEST.MF 文件中,將來我們相當多的工作都是在其中完成。
圖 5. 基本的插件視圖 - 編輯 Activator.java,輸入 hello world 語句,代碼如下:
清單 1. 編輯 Activator.java
package osgi.test.helloworld; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; public class Activator implements BundleActivator { /* * (non-Javadoc) * @see org.osgi.framework.BundleActivator * #start(org.osgi.framework.BundleContext) */ public void start(BundleContext context) throws Exception { System.out.println("hello world"); } /* * (non-Javadoc) * @see org.osgi.framework.BundleActivator * #stop(org.osgi.framework.BundleContext) */ public void stop(BundleContext context) throws Exception { } }
我們可以看到每個 Activator 實際都是實現了
BundleActivator
接口,此接口使 Activator 能夠接受框架的調用。在框架啟動后,啟動每個 bundle 的時候都會調用每個 bundle 的 Activator 。注意:bundle 的 Activator 必須含有無參數構造函數,這樣框架才能使用
Class.newInstance()
方式反射構造 bundle 的 Activator 實例。這里我們在
start
方法中填入了我們希望輸出的 hello world 字符串。那么,怎么才能啟動這個 bundle 呢? - 執行:選擇 Run > Open Run Dialog,進入運行菜單,在 OSGi framework 中右鍵點擊選擇 new 一個新的 OSGi 運行環境,如圖:
圖 6. 新建 OSGi 運行環境
在右邊的運行環境對話框中,輸入運行環境的名字、start level 和依賴的插件,由於我們目前不需要其它的第三方插件,因此只需要勾上系統的 org.eclipse.osgi 插件,如果不選擇此插件,hello world 將無法運行。如圖 7,只有當您點擊了 validate bundles 按鈕 ,並且提示無問題之后,才表明您的運行環境基本 OK 了。
圖 7. 選擇 org.eclipse.osgi插件
依賴插件的選擇:
圖 8. 依賴插件的選擇
好的,如果您的運行環境已經 OK,那么就點擊 Run 吧。
圖 9. 運行 OSGi 項目
恭喜您,成功了!
-
OSGi 控制台
OSGi 控制台對於習慣開發普通 Java 應用程序的開發人員來說,還是比較新鮮的。一般來說,通過 OSGi 控制台,您可以對系統中所有的 bundle 進行生命周期的管理,另外也可以查看系統環境,啟動、停止整個框架,設置啟動級別等等操作。如圖 10,鍵入
SS
就可以查看所有 bundle 的狀態:
圖 10. 查看所有 bundle 的狀態
下面列出了主要的控制台命令:
表 1. Equinox OSGi 主要的控制台命令表
類別 命令 含義 控制框架 launch
啟動框架 shutdown
停止框架 close
關閉、退出框架 exit
立即退出,相當於 System.exit init
卸載所有 bundle(前提是已經 shutdown) setprop
設置屬性,在運行時進行 控制 bundle Install
安裝 uninstall
卸載 Start
啟動 Stop
停止 Refresh
刷新 Update
更新 展示狀態 Status
展示安裝的 bundle 和注冊的服務 Ss
展示所有 bundle 的簡單狀態 Services
展示注冊服務的詳細信息 Packages
展示導入、導出包的狀態 Bundles
展示所有已經安裝的 bundles 的狀態 Headers
展示 bundles 的頭信息,即 MANIFEST.MF 中的內容 Log
展示 LOG 入口信息 其它 Exec
在另外一個進程中執行一個命令(阻塞狀態) Fork
和 EXEC 不同的是不會引起阻塞 Gc
促使垃圾回收 Getprop
得到屬性,或者某個屬性 控制啟動級別 Sl
得到某個 bundle 或者整個框架的 start level 信息 Setfwsl
設置框架的 start level Setbsl
設置 bundle 的 start level setibsl
設置初始化 bundle 的 start level 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 版本聲明