OSGI(Open Service Gateway Initiative),即開放服務網關協議,是面向Java的動態模型系統。
OSGI是指由OSGI Alliance組織制定的Java模塊化規範,OSGI規範的核心部分是一個框架,其中定義了應用程序的生命週期模式和服務註冊。基於OSGI框架定義了大量的OSGI服務:日誌、配置管理,HTTP服務(運行Servlet)、XML解析、設備訪問、軟件包管理、許可管理、用戶管理、IO鏈接、Jini和UPnP等。
OSGI中文社區:http://www.osgi.com.cn/
OSGI官方網站:https://www.osgi.org/
OSGI框架實現了一個優雅、完整和動態的組件模型,組件(bundle)無需從新引導能夠被遠程安裝、啓動、升級和卸載。
OSGI服務平臺提供在多種網絡設備上無需重啓的動態改變構造的功能。
爲了最小化耦合度和促使耦合度可管理,OSGI技術提供了一種面向服務的架構,使組件動態地發現對方。
OSGI聯盟已經開發瞭如HTTP服務器、配置、日誌、安全、用戶管理、XML等不少公共功能標準組件接口。標準組件的兼容性插件實現能夠從不一樣計算機服務提供商獲得。
OSGi的主要職責就是爲了讓開發者可以建立動態化、模塊化的Java系統。java
OSGI規範包括如下子規範:
A、Framework規範(OSGI核心,提供一個安全的可管理的Java Framework來部署可擴展的Java服務)
B、Package Admin Service規範(管理不一樣的Bundle之間的引用關係。當Bundle更新或者卸載時判斷是否有其它的服務正在使用當前的Bundle)
C、Start Level規範(定義了啓動和中止一個OSGi Service Platform時,不一樣的Bundles的啓動或者中止的前後順序)
D、Permission Admin Service規範(Bundle是否許可執行另外的Bundle的代碼)
E、URL Handlers Service規範(怎樣註冊URL Schema,如何將java.io.InputStream對象轉換爲特定的Java對象)
F、Log Service規範
G、Configuration Admin Service規範
H、Device Access Specification
I、User Admin Service Specification
J、IO Connector Service Specification
K、Http Service Specification
L、Preference Service Specification
M、Wire Admin Service Specification
N、XML Parser Service Specification
O、Metatype Specification
P、Service Tracker Specification
Q、Measurment and State Specification
R、Position Specification
S、Execution Environment Specficationshell
OSGI的優點主要表如今如下幾個方面:
A、熱插拔的插件體系結構
基於OSGI的應用程序可動態更改運行狀態和行爲。在OSGI框架中,每個組件都是可熱插拔的,所以,對某一特定的組件的修改並不會影響到容器中的全部組件,運行中的大部分組件依舊能照常工做,部署一個新的Bundle時也不須要從新啓動服務器。
B、可複用性
OSGI框架自己可複用性極強,易於構建真正面向接口的程序架構,每個組件(Bundle)都是一個獨立可複用的單元。基於OSGI獨特的特性,進行企業開發的時候,對於新的開發,能夠從企業的組件庫中精簡出可複用的模塊,量身定作新的組件,最大限度的利用了已有的資源,下降開發成本,加強企業的競爭力。
C、高效性,穩定性
OSGI是一個穩定而高效的系統。OSGI做爲一個微核的系統,其核心只有爲數很少的幾個JAR包。基於OSGI框架的系統的低耦合性,其結構的優點性保證具體的某一個組件不至於影響到全局,更不會由於局部的錯誤致使全局系統的崩潰。apache
A、每一個組件(Bundle)都由單獨的類加載器加載,與一些Java EE項目中使用比較多的框架整合比較困難,如Spring MVC、Struts2等。
B、目前OSGI框架提供的管理端不夠強大,如今的管理端中僅提供了基本的組件狀態管理、日誌查看等功能,像動態修改系統級別的配置(config.ini)、動態修改組件的配置(Manifest.mf)、啓動級別等功能都還沒有提供。
C、採用OSGI做爲規範的模塊開發、部署方式天然給現有開發人員提出了新的要求,須要學習新的基於OSGI的開發方式。編程
OSGI框架從概念上能夠分爲三層:模塊層、生命週期層和服務層。
Module Layer:模塊層主要涉及包及共享的代碼;
Lifecycle Layer:生命週期層主要涉及組件的運行時生命週期管理;
Service Layer:服務層主要涉及模塊之間的交互和通訊。
OSGI Framework是OSGI Service Platform規範的核心組成部分,提供了一個通用的、安全可管理的Java framework。經過OSGI Framework能夠支持一種叫作組件的Service application的部署和擴展。
OSGI兼容設備能夠下載而且安裝OSGI組件,也可一旦再也不須要的時候刪除。組件安裝後會註冊必定數量的Services,並被由同一個Framework下的其它組件使用。
在一個動態擴展的的OSGI環境中,Framework管理組件的安裝和更新,同時也管理組件和Services之間的依賴關係。
Framework提供給組件開發者必須的資源來在Java平臺上開發,爲開發的組件提供了代碼動態加載的功能, 也使得開發者開發、部署一個大規模的Services變的很容易。
其次,Framework爲Java組件開發者提供了簡明一致的編程模型,簡化了開發部署的複雜性。編程模型容許開發者將本身的接口規範綁定到OSGI環境中的Service。
一個一致的編程模型幫助開發者能夠應付一些可估計的危急錯誤。Framework將會運行在不一樣的硬件環境上,但一致的接口確保組件能夠運行在一致的服務接口上。數組
模塊層是OSGi框架中最基礎的部分。
OSGi的模塊化,是經過爲Jar包添加metadata 來定義哪些類該暴露,哪些類該隱藏,其控制單元叫作組件Bundle(jar包)。
Bundle是以jar包形式存在的一個模塊化物理單元,包含代碼、資源文件和元數據(metadata),而且jar包的物理邊界也是運行時邏輯模塊的封裝邊界。
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框架中屬於模塊層上面的一層,生命週期層的運做是創建在模塊層的功能之上的。
生命週期層的主要功能是控制動態安裝、開啓、關閉、更新和卸載組件。
生命週期層可以從外部管理應用或者創建可以自我管理的應用(或者二者的結合),而且給了應用自己很大的動態性。
Bundle的使用須要生命週期層的API與OSGi框架的生命週期層進行交互。網絡
OSGi服務是註冊到OSGi框架中的一個Java對象。註冊的時候能夠設置Service的屬性。而在獲取Service的時候能夠根據屬性進行過濾。
Bundle能夠經過Bundle的上下文去註冊Service或去查詢Service。架構
模塊化是將一個大型系統分解爲多個較小的互相協做的邏輯單元,經過強制設定模塊之間的邏輯邊界來改善系統的維護性和封裝性。
模塊(module)定義了一個邏輯邊界,模塊自己精確地控制哪些類是徹底被封裝起來的,而哪些類須要暴露出來做爲外部使用。開開發者能夠輕鬆地將實現屏蔽在模塊的內部,將公共API暴露在外部。 app
面向對象編程中不會把全部功能都塞到同一個類。面向對象編程從問題域中發現多個事物,每一個事物負責不一樣的功能,儘可能作到高內聚和低耦合。面向對象的模塊化粒度在類級別上。
OSGi的模塊化是經過爲JAR包添加metadata來定義哪些類應該暴露哪些類又隱藏在包中,其控制可見性的粒度是在組件(JAR包)層面上的。
OSGI模塊化和麪向對象思想所帶來的能力都是經過控制可見性和可用性來保證高內聚和低耦合的,但粒度不一樣,一個是組件層面上,一個是對象層面上。
A、底層代碼的可見性控制
Java提供了private、public、protected和package private(無修飾符)四種訪問控制級別,提供了底層的OO數據封裝特性。Packege具備分割代碼的做用,但若是包中的代碼要對包外可見,必須設置爲public(protected,使用繼承)。
org.serc.helloworld.Hello.java:定義了一個接口
package org.serc.helloworld; public interface Hello { void sayHello(); }
org.serc.helloworld.impl.HelloImpl.java:實現了Hello接口
package org.serc.helloworld.impl; import org.serc.helloworld.Hello; public class HelloImpl implements Hello{ final String helloString; public HelloImpl(String helloString){ this.helloString = helloString; } public void sayHello(){ System.out.println(this.helloString); } }
org.serc.helloworld.main.Main.java文件:
package org.serc.helloworld.main; import org.serc.helloworld.Hello; import org.serc.helloworld.HelloImpl; public class Main{ final String helloString; public static void main(String[] args){ Hello hello = new HelloImpl(「Hello,SERC!」); hello.sayHello(); }
三個文件分別在不一樣的包中。HelloImpl實現細節不該該暴露給其它包,但從Main.java的main方法中能夠看出,爲了建立Hello的實例,必須引入HelloImpl類,可是HelloImpl做爲接口的實現細節,不該該暴露給使用者,違反了封裝的原則。
若是不想讓HelloImpl暴露出來,須要作額外的工做保證既隱藏了實現細節,又能簡單的建立一個實現了Hello接口的實例。能夠經過多種方法(好比工廠模式)來實現,但增長了與應用自己功能無關的多餘工做,是Java的侷限。
B、classpath的侷限
在classpath中加入jar包的時候,只給出文件路徑,而jar包的版本、一致性、依賴性,沒法在classpath中明確的設置或是從classpath中看出相應屬性。
classpath中的jar包是按序加載的,例如:
classpath=/servlet2.2/servlet.jar;/servlet2.3/servlet.jar, 在實際應用的過程當中,Java使用servlet2.2,而不是servlet2.3。若是在大型系統中團隊分開開發時,各用各的servlet包,而且版本號不同,在最後將開發結果合併的時候,用的是哪一個版本的servlet包就很難搞清楚。
即便classpath能注意到版本的問題,也無法精確指出依賴。開發者須要根據提示信息增長依賴包,直到虛擬機不運行到缺包異常爲止。
C、OSGI對JAVA侷限的改善
OSGi中很好解決了JAVA的侷限性:
包的可見性:OSGi經過引入包的可見性機制,可以徹底控制一個包中的代碼對哪些模塊可見,而不只僅侷限於無差異的可見性,從而完善了Java的代碼訪問控制機制。
包的版本:OSGi經過爲包增長版本信息,能夠精確控制代碼的依賴,保證代碼的版本一致性,彌補了classpath的缺點。
組件(bundle)是以jar包形式存在的一個模塊化物理單元,包含了代碼、資源文件和元數據(metadata),而且jar包的物理邊界也是運行時邏輯模塊的封裝邊界。
在標準的jar包的manifest文件中添加一些組件(bundle)的模塊化特徵(metadata)後,jar包就變成了一個bundle。
bundle和普通jar包最大的區別就在於元數據。
Bundle元數據的目的在於準確描述模塊化相關的bundle特徵,讓OSGi框架對bundle進行各類處理工做(好比依賴解析,強制封裝等),元數據主要有三部分:
A、可讀信息(可選)
OSGi標準定義了幾個元數據條目幫助更好地理解和使用bundle,但全部的條目都不是必須的,而且不對模塊化特性產生任何的影響,OSGi框架會徹底無視可讀信息。
Bundle-Name: SERC Helloworld Bundle-Vendor: GR, SERC Bundle-DocURL: http://elevenframework.org Bundle-Category: example Bundle-Copyright: SERC
B、bundle標識符(必須)
bundle標識符用於惟一的標識一個bundle。
早期的OSGi標準中並無提供標識一個已知bundle的方法,直到OSGi R4標準,「惟一bundle標識符」被提出來。爲了向後兼容,Bundle-Name不能用來做爲標識符,不然就會增長維護向後兼容的工做,因此使用新的manifest屬性Bundle-SymbolicName。Bundle-SymbolicName: org.serc.helloworld
Bundle-Name是給用戶讀的,而Bundle-SymbolicName是給OSGi框架讀的,讓OSGi框架可以惟一標識一個bundle。
只用一個Bundle-SymbolicName確定是能夠惟一標識一個bundle,可是隨着時間的推移,bundle可能會有新版本,加入版本屬性會讓bundle的信息更加準確。
Bundle-Name: SERC Helloworld Bundle-Vendor: GR, SERC Bundle-DocURL: http://elevenframework.org Bundle-Category: example Bundle-Copyright: SERC
C、代碼可見性(必須)
代碼可見性用於定義內部與外部代碼。在JavaSE中的jar包若是放在classpath裏,那麼jar包對classpath下的全部程序都是可見的,而且可見性不能改變。而OSGi標準定義了以下的屬性用於描述代碼的可見性:
Bundle-ClassPath:定義了造成bundle的全部代碼所在的位置,Java 中的classpath是定義的jar包的位置,而Bundle-ClassPath屬性描述的是bundle內部類在bundle中的路徑。例如:Bundle-ClassPath:.,other-classes/,embedded.jar
Export-Package:顯式暴露須要和其它bundle共享的代碼,每一個包之間用逗號分隔,每一個包可用修飾詞來修飾包的其它特徵。
Export-Package: org.serc.hellworld; vendor=」SERC」, org.serc.hellworld.impl; vendor=」Gou Rui」
Import-Package:定義bundle所依賴的外部代碼,其格式和Export-Package相同,而且也可使用修飾詞來修飾包。修飾詞是用來限制所依賴包的範圍的,相似過濾器,而不像Export-Package中用來聲明包的特徵。例如: Import-Package: org.serc.helloworld; vendor=」SERC」
生命週期層在OSGi框架中屬於模塊層上面的一層,其運做創建在模塊層的功能之上的。生命週期層主要功能是讓開發者可以從外部管理應用或者創建可以自我管理的應用(或者二者的結合),而且給應用自己很大的動態性。
通常來講,程序(或者程序的一部分)都必定服從某種生命週期。軟件的生命週期有4個典型的階段,以下:
若是正在建立一個應用,首先得安裝(install)應用;當應用的全部依賴都知足,能夠執行應用;若是應用再也不須要,能夠中止(stop);一段時間後,可能須要更新(update)應用的版本;最終,可能會移除(remove)應用。
經過在外部或者內部對應用進行操做,完成對應用的生命週期管理過程。對於非模塊化應用,操做是以整個應用爲對象的;對於模塊化應用,能夠有更細粒度(針對應用中的某個模塊)的生命週期管理。
要想使用組件(bundle),就得使用生命週期層的API與OSGi框架的生命週期層進行交互。
OSGi框架的核心並無強制使用任何特定的API交互機制(好比命令行,GUI,或者XML配置文件等),只是單純的Java API而已,開發者能夠任意創造出本身想要的交互模式,保證了框架的靈活性。
在標準的Java編程中,會經過將jar包放到classpath中來使用jar包,而bundle不一樣。Bundle只有在被安裝(install)到一個OSGi框架的運行實例中才能用起來,而且OSGi框架支持對bundle完整的生命週期管理,而且支持這些管理操做在應用執行完成,其動態性可見一斑。
Bundle生命週期的狀態轉移圖以下:
能夠經過Bundle的getState方法來得到bundle的當前狀態。
Starting和Stopping狀態是暫態,在持續一下子後就會自動轉移到下一個狀態,不須要轉移條件。
生命週期層的API主要由BundleActivator、BundleContext、Bundle三個核心接口組成。
A、BundleActivator
BundleActivator讓開發者可以捕捉bundle的start和stop事件,並對做出自定義的反應。
BundleActivator的接口定義以下:
public interface BundleActivator { public void start(BundleContext context) throws Exception; public void stop(Bundlecontext context) throws Exception; }
若是一個類實現了BundleActivator接口,那麼類就成爲一個Activator。但有實現是不夠的,要讓OSGi框架知道Activator的存在。因此還須要在MANIFEST文件中添加以下一項屬性: Bundle-Activator:org.demo.Activator
當bundle啓動(start)的時候,OSGi框架就會調用Activator的start方法,一樣的也適用與stop方法。
並非每一個bundle都須要一個activator,有時候bundle只是爲了和其它bundle分享代碼,而並不須要在啓動和中止的時候作出多餘的動做。是否使用BundleActivator藉口,須要具體問題具體分析。
B、BundleContext
BundleContext是bundle在框架中的執行時上下文,提供了與框架進行交互的方法。
BundleContext接口中的方法主要分爲兩類,一類與部署和生命週期管理相關,另外一類是關於利用服務層進行bundle間交互的方法。
public interface BundleContext { String getProperty(String key); Bundle getBundle(); Bundle installBundle(String location, InputStream input) throws BundleException; Bundle installBundle(String location) throws BundleException; Bundle getBundle(long id); Bundle[] getBundles(); void addBundleListener(BundleListener listener); void removeBundleListener(BundleListener listener); void addFrameworkListener(FrameworkListener listener); void removeFrameworkListener(FrameworkListener listener); }
BundleContext接口對於與其相關的bundle來講都是惟一的執行上下文,而且只有在bundle是屬於active狀態的時候執行時上下文才是有意義的,即在start方法被調用和stop方法被調用的兩個時間點之間。若是一個bundle沒有處於active時間段,但組件的bundlecontext對象被使用,框架會拋出異常。
框架使用這個上下文對象還有一個目的就是爲了bundle的安全和資源分配,因此BundleContext對象應該被當作私有對象,不該該被隨意在bundle之間傳遞。
C、Bundle
Bundle在邏輯上表示一個bundle,OSGi環境中的一個物理bundle對應一個bundle對象。bundle對象中包含了bundle的基本信息和bundle聲明週期的控制接口。
在BundleContext接口中,getBundle方法能夠獲得Bundle對象。
對於每一個被安裝到框架中的bundle,框架都建立一個Bundle對象在邏輯上表達之。Bundle接口中定義了bundle生命週期管理的方法:
public interface Bundle { BundleContext getBundleContext(); long getBundleId(); Dictionary getHeaders(); Dictionary getHeaders(String locale); String getLocation(); int getState(); String getSymbolicName(); Version getVersion(); void start(int options) throws BundleException; void start() throws BundleException; void stop(int options) throws BundleException; void stop() throws BundleException; void update(InputStream input) throws BundleException; void update() throws BundleException; void uninstall() throws BundleException; }
大部分OSGi框架的實現都是將locatioin解釋爲指向OSGi bundle的一個URL,在須要的時候就會經過URL將bundle下載到框架中來安裝使用。但OSGi標準沒有規定location的形式必須是URL,並且URL也並非非要不可的,還能夠經過輸入流(Input Stream)來安裝bundle。
bundle不能本身改變本身的狀態,好比說一個active的bundle不能stop本身,stop本身就會拋出異常。
服務是服務提供者和服務使用者之間的一個契約。使用者通常不關心服務實現的細節,只關心是否知足契約(服務應該提供什麼功能,知足什麼格式)。使用服務的過程包含了發現服務和達成協議的形式,須要經過服務的標誌性特徵來找到對應的服務。
服務層是OSGi框架中最上面的一層,服務層帶來了更多的動態性,而且使用了面向服務編程模型。當一個bundle發現開始使用OSGi中的一個服務後,服務可能在任何的時候改變或者是消失。
OSGi框架有一箇中心化的註冊表,註冊表聽從publish-find-bind模型:
一個提供服務的bundle能夠發佈POJO做爲服務的實體;一個使用服務的bundle能夠經過註冊表找到和綁定服務。
能夠經過BundleContext接口來完成服務的發佈、發現、綁定,以下:
public interface BundleContext { void addServiceListener(ServiceListener listener, String filter) throws InvalidSyntaxException; void addServiceListener(ServiceListener listener); void removeServiceListener(ServiceListener listener); ServiceRegistration registerService(String[] clazzes, Object service, Dictionary properties); ServiceRegistration registerService(String clazz, Object service, Dictionary properties); ServiceRegistration[] getServiceReferences(String clazz, String filter) throws InvalidSyntaxException; ServiceRegistration[] getAllServiceReferences(String clazz, String filter) throws InvalidSyntaxException; ServiceReference getServiceReference(String clazz); Object getService(ServiceReference reference); boolean ungetService(ServiceReference reference); }
爲了讓其它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();
ServiceRegistration對象不能和其它Bundles共享,由於ServiceRegistration對象和發佈服務的bundle的生命週期相互依存。若是bundle已經不在框架執行環境中存在,那麼ServiceRegistration對象也不該該存在。
代碼中的參數new LSE()是一個POJO,不須要實現任何OSGi類型或者使用標註,只要知足服務約定就能夠。
若是在刪除發佈的服務前bundle以及中止,框架會幫助刪除服務。
能夠根據服務約定從註冊表中找到正確的服務。發現服務並得到其引用的接口以下:
ServiceReference reference = bundleContext.getServiceReference(StockListing.class.getName());
reference是服務對象的間接引用,不直接使用服務對象是爲了將服務的使用和服務的實現進行解耦,將服務註冊表做爲二者的中間人,達到跟蹤和控制服務的目的,同時還能夠在服務消失後通知使用者。
ServiceReference能夠在bundle之間互享,與使用服務的bundle的生命週期無關。
在getServiceReference方法中,選擇service的默認優先級是先選擇service.rank最高的,在rank相等的狀況下選擇最先在框架中註冊的。除了默認的規則,還能夠在getServiceReferences中經過添加過濾參數(做爲調用該方法的第二個參數)來作一些篩選。
ServiceReference[] references = bundleContext.getServiceReferences(StockListing.class.getName(), 「(&(currency=GBP)(objectClass=org.example.StockChart))」);
匹配參數是一個字符串,字符串的格式屬於LDAP查詢格式,在RFC1960標準中有完整的描述。
字符串中等號左邊的內容是元數據(Dictionary)中的左值,經過左值對應的右值與服務的元數據進行匹配。匹配示例以下:
屬性匹配:
(name=John Smith) (age>=20) (age<=65)
模糊匹配: (name~=johnsmith)
通配符匹配: (name=Jo*n*Smith*)
判斷某個屬性是否存在: (name=)
條件與: (&(name=John Smith)(occupation=doctor))
條件或: (|(name~=John Smith)(name~=Smith John))
*條件非: ** (!(name=John Smith))
發現服務後,使用服務以前,必須從註冊表中綁定實現的服務。
StockListing listing = (StockListing) bundleContext.getService(reference);
返回的POJO實例和在註冊表中註冊的實例是同一個。
每次使用getService方法的時候,註冊表會將對應服務的使用次數加1,同時會記錄誰在使用該服務。若是不想使用服務的,註銷服務。
bundleContext.ungetService(reference); listing = null;
OSGI是OSGi Alliance組織制定的Java模塊化規範,但OSGI聯盟並無給出OSGI容器的實現,具體實現由第三方廠商完成,目前使用較多的OSGI容器有Apache Felix、Equinox、Spring DM。
A、Apache Felix
Apache Felix是Apache旗下的一個OSGi框架,Felix是一個OSGi版本4規範的Apache實現。Apache Felix提供的服務幾乎涵蓋了所有的OSGi 4.2的標準,除此以外還提供了一些非標準的功能,例如iPOJO。Apache Felix框架自己很是緊湊,只須要3個包加一個shell就能夠運行,不管是開發仍是Debug都很是簡便。
B、Equinox
Equinox是Eclipse旗下的OSGi框架,自己也被Eclipse採用,是Eclipse的PDE開發環境的底層。Equinox自己也是至關的全面的框架,提供的功能不比Felix少多少。Equinox被當作開發Eclipse Plugin的應用較多,若是要開發一個Web程序,就會感到功能和文檔不夠全面。Equinox最大的優點在於和Eclipse結合緊密,只要安裝了PDE,就已經有了Equinox,能夠方便的在Eclipse裏設置開發的Bundle,啓動、部署等操做也異常簡單,並且有專門的Debug界面。
C、Spring DM
Spring DM是Spring旗下的OSGi框架,Spring DM的最大特色是結合了Spring框架。
D、Knopflerfish
Knopflerfish是OSGi的先行者,是一個至關標準OSGi框架,提供了絕大多數標準功能。
A、CTK Plugin Framework
CTK是基於Qt開發的支持生物醫學影像計算的開源項目。
CTK中的CTK Plugin Framework模塊借鑑了OSGI的思想,並實現了幾乎完整的OSGI框架API。
B、C++ Micro Services
C++ Micro Services是基於OSGI思想的用於建立和管理模塊化軟件系統的C++庫。
Apache Celix是基於C/C++的OSGI規範實現,提供了一個使用組件和麪向服務編程(SOP)開發模塊化應用的框架。
Apache Celix主要使用C語言開發,爲了支持C++,以庫的形式增長了抽象。
官方網站:http://celix.apache.org/