OSGi基本概念初探
2007-10-23 21:16:45
轉載,原文地址: http://dev2dev.bea.com.cn/blog/chrisrc/200710/23_528.html
深入Java技術,關注分布式數據交換,關注企業應用集成,關注OSGi、JBI、SCA、SOA、EAI、ESB、JXTA、JINI.. ... 關注EQUINOX/RCP/RAP/ECF/DTP/STP/GEF/EMF......
1、OSGi是什么
OSGi是什么,OSGi是一種松散耦合的組件管理和服務運行平臺規范。簡單的說,用戶只需要修改通用的Java類庫打包檔案JAR文件中META- INF下的元數據文件MANIFEST.MF,添加必要的標簽信息,放置到OSGi框架的Bundle Repository中,用戶的類庫就成了OSGi環境的一部分。
成為OSGi環境的組件為其他標準的OSGi組件提供代碼功能是最直接的一種。用戶也可以將提供組件中的某種功能的接口和實現實例發布到OSGi服務注冊表中,供其他組件直接查找使用。同樣,用戶可以查找OSGi環境中其他組件提供的接口服務,調用該服務完成必要的處理。
OSGi組件提供的服務具有兩個層面的含義:系統層面,即一個組件為其他組件提供服務,這些服務體現為Java接口的實現;業務層面,即一個組件為外部系統或用戶提供某種業務服務實現。
2、OSGi提供的功能
OSGi能夠提供什么功能呢?我們將OSGi運行平臺與常用的Web應用服務服務器做一個比較,來看OSGi提供的功能。首先,以tomcat為例,在 tomcat容器中可以運行多個Web應用,假設存在兩個Web應用A和Web應用B,一般說來,Web應用A和B具有各自的運行空間,兩者之間不存在任何關聯,A和B具有自己獨立的生命周期,如部署、啟動、停止和卸載等。
那么,是如何做到這一點的呢?很明顯,這是通過JVM的類加載機制決定的。當tomcat運行并啟動Web應用A和B時,tomcat為Web應用A和B 各自構建了一個類空間,也可以看作是一個類域(Class Domain),Web應用A的類域包括JRE中的類,tomcat啟動類路徑上的類和Web應用A中WEB-INF目錄下classes目錄下的類和 lib中的jar包;同樣,Web應用B也有自己獨立的類域,其范圍除了JRE中的類,tomcat啟動類路徑上的類之外就是自己內部WEB-INF目錄下classes目錄下的類和lib中的jar包。如下圖所示:
現在提出一個問題,如果Web應用A需要使用Web應用B提供的Java類,怎么辦?實現方式有多種,一種是將B提供的類打包,放置到應用A的WEB- INF/classes或WEB-INF/lib中;也可以將B提供的類放置到tomcat的類路徑上,甚至是JRE的擴展目錄下,但這樣做在實際使用中或多或少存在一些問題。能不能在運行時Web應用A可以直接使用Web應用B提供的類呢?在運行時Web應用B能不能提供一個接口的實現,即類實例,由 Web應用A使用呢?能不能提供一個應用C為應用A和應用B提供服務呢?顯然,這些對于Web容器是不行的。
帶著上述問題我們回到OSGi運行平臺。可以將OSGi看作是Web容器的泛化,是更高級別的抽象。運行在OSGi環境中的類似于Web容器中的Web應用的組件即Bundle,不再僅僅局限于一個業務應用的概念,它的粒度更加精細,即可以看作是一個Jar包,為其他Bundle提供幫助類;也可以是一個 HTTP服務組件,為其他Bundle提供http服務;還可以是一個Web容器,為其他Bundle提供Web應用服務。
那么,能不能解決上述提到的問題呢?我們假設在OSGi運行平臺中包含了3個Bundle:A、B和C。
- 對于問題一:Bundle A需要使用Bundle B中的某些實現類,如何實現?
可以將Bundle B中的這些類通過Bundle B的元數據描述信息公開(Export)出去,使得這些類對OSGi平臺中的所有Bundle可見,這些類資源仍然位于Bundle B中。Bundle A在其元數據描述信息中將Bundle B公開的類引入(Import)進來。在運行時,Bundle A就可以使用Bundle B提供的這些類,而不是需要將這些類拷貝到Bundle A中或其他位置。
- 對于問題二:Bundle A可不可以直接使用Bundle B在運行時構建了類實例?
Bundle B在運行時可以將Bundle A需要的類實例注冊到OSGi運行平臺的服務注冊表中,類實例實現的接口可以通過上述問題一的方式使得Bundle A可見,那么,在運行時,Bundle A就可以通過該接口到OSGi平臺服務注冊表中查找Bundle B中提供的接口實現類實例,并調用該接口上的方法。
- 現在來看問題三:Bundle C能不能為Bundle A和Bundle B共享呢?
可以將上述問題二的解決方案中的Bundle B提供的接口定義提取到Bundle C中,并在Bundle C的元數據中公開,通過在Bundle A和Bundle B中同時引入Bundle C中發布的接口,Bundle B提供該接口的實現,Bundle A使用該接口實現提供的功能。這一切看上去是不是解決的非常完美呢?!
3、OSGi的實現機制
OSGi是如何實現的呢?從本質上說,OSGi是充分使用了Java的類加載機制,對模塊和應用進行了更加精細粒度的控制,然后在類域上建立一系列松耦合應用。OSGi為每一個Bundle組件定義了一些元數據信息,通過這些元數據,OSGi在運行時為每一個Bundle構建了一個獨立的類域(即類空間),詳細描述參考OSGi之Bundle小節。
4、OSGi的組成
OSGi在R4種將功能分為幾層,包括:安全層、模塊層、生命周期層、服務層和實際的服務。OSGi的核心實現即為OSGi框架,它本身也是一個OSGi Bundle。
- OSGi的安全層(Security Layer)是一個可選的實現,該層基于Java2 安全架構,位于OSGi服務平臺的底層對OSGi環境中應用的部署和管理提供更好的安全控制。
- OSGi的模塊層(Module Layer)為基于Java的應用、組件的打包,部署和校驗提供了一個通用的標準化的解決方案。其他類似的解決方案如JBoss、NetBeans。
- 生命周期層(Life Cycle Layer)為Bundle組件的安全和生命周期操作提供了API定義,該層位于安全層和模塊層之上。
- 服務層(Service Layer)定義了一個與生命周期層緊密結合的組件動態交互模型。OSGi中的服務是實現了一個或多個Java接口的Java對象,通過將這些對象依據其實現的接口注冊到服務注冊表中,Bundle組件可以發布自己的服務,查找使用服務,注冊監聽處理服務的狀態變更等。
- 實際的服務(Actual Services)是OSGi定義的一些標準的服務接口如日志服務(Log Service),包管理服務(Package Admin Service)、啟動級別服務(Start Level Service)、HTTP服務(Http Service)、配置服務(Config Admin Service)、用戶管理服務(User Admin Service)等等,詳細的服務定義參考OSGi規范。
5、OSGi之Bundle
OSGi中的重要元素就是Bundle 和Service,Bundle提供了一種靜態資源邊界,類似于Web容器中的Web應用的概念。
每一個Bundle通過一個元數據文件(MANIFEST.MF)描述。OSGi框架(即SystemBundle)通過解析這個元數據文件對該 Bundle進行加載和管理。Bundle通過元數據中的"Export-Package"屬性將內部的類包發布給OSGi系統中其他Bundle使用,通過"Import-Package","Requie-Bundle"屬性引用OSGi系統中其他Bundle發布的類包。
每一個Bundle有自己獨立的類加載器(Fragment Bundle例外,其資源通過其Host Bundle加載),Bundle內部的資源(類,文件等)通過該類加載器查找和加載。Bundle的類加載器能夠控制的類加載邊界包括:啟動類路徑上的類資源,OSGi框架即SystemBundle上的類資源和Bundle內部的類資源。該類資源邊界即形成該Bundle的類域。
每一個Bundle在OSGi框架中具有自己的生命周期,其生命周期內的狀態包括:INSTALLED、RESOLVED、STARTING、ACTIVE、STOPPING和UNINSTALLED。
INSTALLED狀態是Bundle的初始狀態,當該Bundle部署到OSGi系統的Bundle Repository中時,Bundle的狀態標記為INSTALLED。
Bundle內部的資源在加載之前,首先由OSGi框架對其進行解析(Resolve),解析的過程就是分析Bundle的元數據的過程,詳細過程參考OSGi規范。解析后的Bundle進入RESOLVED狀態,解析失敗時,仍然處于INSTALLED狀態。
Bundle內的資源被其它Bundle使用時,該Bundle被啟動,也可以通過設定讓OSGi框架在加載該Bundle時直接啟動。
Bundle內的資源通過BundleContext與其他Bundle進行交互。元數據中的"Bundle-Activator"屬性指定了實現 BundleActivator接口的實現類,Bundle通過該類得到BundleContext,通過BundleContext可以查找其他的 Bundle,查找注冊在OSGi中的服務(Service)與OSGi環境進行交互等等。Bundle可以在其提供的BundleActivator實現類中進行初始化的工作,也可以注冊服務到OSGi的服務注冊表中,供其他Bundle查找使用。
6、開源的OSGi實現
Knopflerfish:http://www.knopflerfish.org
Oscar:http://oscar.objectweb.org
Equinox:http://www.eclipse.org/equinox
Flex:http://felix.apache.org
【
趙斌原創,保留一切權利,轉載請保留引用:
m.tkk7.com/zhaobin,注明轉載除外,謝謝!】