OSGi 基本原理


定義


OSGi(Open Service Gateway Initiative)技術是面向Java的動態模型系統。

這個框架實現了一個優雅、完整和動態地組價模型。應用程序(稱為bundle)無序重新引導可以被遠程安裝、啟動、升級和卸載。

OSGi服務平台提供在多種網絡設備上無需重啟的動態改變構造的功能。

為了最小化耦合度和促使這些耦合度可管理,OSGi技術提供一種面向服務的架構,它能使這些組件動態地發現對方。

OSGi聯盟已經開發了例如像HTTP服務器、配置、日志、安全、用戶管理、XML等很多公共功能標准組件接口。這些組件的兼容性插件實現可以從進行了不同優化和使用代價的不同計算機服務提供商得到。然而,服務接口能夠基於專有權基礎上開發。

OSGi的主要職責就是為了讓開發者能夠創建動態化、模塊化的Java系統。

 

OSGi 框架


OSGi框架從概念上可以分為三層:模塊層、生命周期層和服務層。

  • Module Layer:模塊層主要涉及包及共享的代碼;
  • Lifecycle Layer:生命周期層主要涉及Bundle的運行時生命周期管理;
  • Service Layer:服務層主要涉及模塊之間的交互和通信。
圖 1. OSGi 層次結構

 

模塊層


模塊層是 OSGi 框架中最基礎的部分。

OSGi 的模塊化,是通過為 Jar 包添加metadata 來定義哪些類該暴露,哪些類該隱藏,其控制單元叫做 Bundle(jar 包)。

Bundle

首先,必須先了解一個基本概念——什么是Bundle?

什么是 Bundle ?
bundle 是以 jar 包形式存在的一個模塊化物理單元,里面包含了代碼,資源文件和元數據(metadata),並且jar包的物理邊界也同時是運行時邏輯模塊的封裝邊界。
bundle

 

如何定義 Bundle

Bundle 是 OSGi 中的基本組件,其表現形式仍然為 Java 概念中傳統的 Jar 包。
通過 META-INF 目錄下的 MANIFEST.MF 文件對其予以進一步的定義。

通常一個 MANIFEST.MF 文件的內容如下:

Manifest-Version: 1.0
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進行理解。

 

生命周期層


 

生命周期層在OSGi框架中屬於模塊層上面的一層,它的運作是建立在模塊層的功能之上的。
生命周期層的主要功能是控制動態安裝、開啟、關閉、更新和卸載的bundles。

生命周期層讓你能夠從外部管理應用或者建立能夠自我管理的應用(或者兩者的結合),並且給了應用本身很大的動態性。

前面已經了解了 Bundle 的概念和作用。但是要真正使用 Bundle,需要使用生命周期層的API,來和OSGi框架的生命周期層進行交互。

在標准的Java編程中,可以通過將jar包放到classpath中來使用它。而bundle則不是這樣,Bundle只有在被安裝(install)到一個OSGi框架的運行實例中才能用起來。並且OSGi框架支持對這些bundle完整的生命周期管理,並且支持這些管理操作在應用執行完成。

下圖為 Bundle 生命周期的狀態轉移圖:

 

http://assets.osgi.com.cn/article/7289216/lifecycle2.png

 

重要接口

生命周期層的API主要是由以下三個核心接口來組成的:BundleActivator,BundleContext 和 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可以通過這個注冊表找到和綁定服務。 

http://assets.osgi.com.cn/article/7289220/service1.PNG

 

發布服務

為了讓別的bundle能發現這個服務,你必須在發布它之前對其進行特征描述。這些特征包括接口的名字(可以是名字的數組),接口的實現,和一個可選的java.util.Dictionary類型的元數據信息。

String[] interfaces =   new String[]{StockListing. class.getName(), StockChart. class.getname()};  
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); 
在上面的代碼中,我們得到了 ServiceRegistration 對象,我們可以用這個對象來更新服務的元數據:
registration.setProperties(newMetadata);
也可以直接就把這個服務移除:
registration.unregister();
需要注意的是這個對象不能和其他 Bundle 共享,因為它和發布服務的bundle的生命周期相互依存。

也就是說,如果這個 Bundle 已經不在框架執行環境中存在,那么這個對象也不應該存在了,“皮之不存毛將焉附”就是這個道理。

試想如果這個 ServiceRegistration 共享給了其他的 bundle(具體的說就是其他bundle中存在對這個對象的引用),那么發布服務的那個bundle即使被移除了,由於其他bundle中的引用依然存在,那么垃圾處理機制不會抹去這個對象,這樣不但於理不合,而且實際上這個對象也是不可用的,因為這個對象所依存的bundle已經不在了。
代碼中的參數new LSE()是一個POJO,這個對象不需要實現任何OSGi類型或者使用標注,只要滿足服務約定(這里就是接口)就可以了。

此外,如果在刪除發布的服務之前bundle停止了,框架會幫助你刪除這些服務。

 

發現和綁定服務

以下是一個根據實現的接口名稱獲得的服務的最簡單方法:
ServiceReference reference =  
bundleContext.getServiceReference(StockListing. class.getName());

注意這里的reference是服務對象的間接引用,可是為什么要用間接引用而不直接返回那個實際的服務對象呢?

實際上是為了將服務的使用和服務的實現進行解耦,將服務注冊表作為兩者的中間人,達到跟蹤和控制服務的目的,同時還可以在服務消失了以后通知使用者。

這個方法的返回類型是ServiceReference,它可以在bundle之間互享,因為它和使用服務的bundle的生命周期無關。

 

參考資料


 

OSGi入門篇:模塊層

OSGi入門篇:生命周期層 

OSGi入門篇:服務層 

OSGi原理與最佳實踐
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM