定義
這個框架實現了一個優雅、完整和動態地組價模型。應用程序(稱為bundle)無序重新引導可以被遠程安裝、啟動、升級和卸載。
為了最小化耦合度和促使這些耦合度可管理,OSGi技術提供一種面向服務的架構,它能使這些組件動態地發現對方。
OSGi聯盟已經開發了例如像HTTP服務器、配置、日志、安全、用戶管理、XML等很多公共功能標准組件接口。這些組件的兼容性插件實現可以從進行了不同優化和使用代價的不同計算機服務提供商得到。然而,服務接口能夠基於專有權基礎上開發。
OSGi的主要職責就是為了讓開發者能夠創建動態化、模塊化的Java系統。
OSGi 框架
OSGi框架從概念上可以分為三層:模塊層、生命周期層和服務層。
- Module Layer:模塊層主要涉及包及共享的代碼;
- Lifecycle Layer:生命周期層主要涉及Bundle的運行時生命周期管理;
- Service Layer:服務層主要涉及模塊之間的交互和通信。

模塊層
模塊層是 OSGi 框架中最基礎的部分。
OSGi 的模塊化,是通過為 Jar 包添加metadata 來定義哪些類該暴露,哪些類該隱藏,其控制單元叫做 Bundle(jar 包)。
Bundle
首先,必須先了解一個基本概念——什么是Bundle?

如何定義 Bundle
通常一個 MANIFEST.MF 文件的內容如下:
Bundle-ManifestVersion: 2
Bundle-Name: Util
Bundle-SymbolicName: com.ibm.director.la.util
Bundle-Version: 1.0.0
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Import-Package: org.osgi.framework;version="1.3.0"
Export-Package: com.ibm.director.la.util;uses:="org.osgi.framework"
Bundle-ClassPath: lib/junit.jar,
MANIFEST.MF 文件存儲的實際上是 Bundle 的元數據。
元數據的內容可以精確的定義 Bundle 的各種特征,同時能更好的對 Bundle 進行標識同時幫助用戶對Bundle進行理解。
生命周期層
生命周期層讓你能夠從外部管理應用或者建立能夠自我管理的應用(或者兩者的結合),並且給了應用本身很大的動態性。
前面已經了解了 Bundle 的概念和作用。但是要真正使用 Bundle,需要使用生命周期層的API,來和OSGi框架的生命周期層進行交互。
下圖為 Bundle 生命周期的狀態轉移圖:

重要接口
- BundleActivator:讓你能夠捕捉bundle的start和stop事件,並對這兩個事件作出自定義的反應。
- BundleContext:一個bundle在框架中的執行時上下文,這個上下文提供了和框架進行交互的方法。
- Bundle:在邏輯上表示了一個bundle,OSGi環境中的一個物理bundle對應了一個bundle對象。該對象中包含了bundle的基本信息和bundle生命周期的控制接口。
服務層
一個OSGi 服務就是注冊到 OSGi 框架中的一個 Java 對象。注冊的時候可以設置這個 Service 的屬性。而在獲取 Service的時候可以根據屬性進行過濾。
Bundle 可以通過 Bundle的上下文去注冊Service或去查詢Service。
一個提供服務的bundle可以發布POJO作為服務的實體;一個使用服務的bundle可以通過這個注冊表找到和綁定服務。

發布服務
例
Dictionary metadata = new Properties();
metadata.setProperty(“name”, “LSE”);
metadata.setProperty(“currency”, Currency.getInstance(“GBP”));
metadata.setProperty(“country”, “GB”);
ServiceRegistration registration = bundleContext.registerService(interfaces, new LSE(), metadata);
也就是說,如果這個 Bundle 已經不在框架執行環境中存在,那么這個對象也不應該存在了,“皮之不存毛將焉附”就是這個道理。
試想如果這個 ServiceRegistration 共享給了其他的 bundle(具體的說就是其他bundle中存在對這個對象的引用),那么發布服務的那個bundle即使被移除了,由於其他bundle中的引用依然存在,那么垃圾處理機制不會抹去這個對象,這樣不但於理不合,而且實際上這個對象也是不可用的,因為這個對象所依存的bundle已經不在了。
代碼中的參數new LSE()是一個POJO,這個對象不需要實現任何OSGi類型或者使用標注,只要滿足服務約定(這里就是接口)就可以了。
此外,如果在刪除發布的服務之前bundle停止了,框架會幫助你刪除這些服務。
發現和綁定服務
bundleContext.getServiceReference(StockListing. class.getName());
注意這里的reference是服務對象的間接引用,可是為什么要用間接引用而不直接返回那個實際的服務對象呢?
實際上是為了將服務的使用和服務的實現進行解耦,將服務注冊表作為兩者的中間人,達到跟蹤和控制服務的目的,同時還可以在服務消失了以后通知使用者。
這個方法的返回類型是ServiceReference,它可以在bundle之間互享,因為它和使用服務的bundle的生命周期無關。
參考資料