OSGI(Open Service Gateway Initiative),即開放服務網(wǎng)關協(xié)議,是面向Java的動態(tài)模型系統(tǒng)。
OSGI是指由OSGI Alliance組織制定的Java模塊化規(guī)范,OSGI規(guī)范的核心部分是一個框架,其中定義了應用程序的生命周期模式和服務注冊?;贠SGI框架定義了大量的OSGI服務:日志、配置管理,HTTP服務(運行Servlet)、XML解析、設備訪問、軟件包管理、許可管理、用戶管理、IO連接、Jini和UPnP等。
OSGI中文社區(qū):http://www.osgi.com.cn/?
OSGI官方網(wǎng)站:https://www.osgi.org/
OSGI框架實現(xiàn)了一個優(yōu)雅、完整和動態(tài)的組件模型,組件(bundle)無需重新引導可以被遠程安裝、啟動、升級和卸載。
OSGI服務平臺提供在多種網(wǎng)絡設備上無需重啟的動態(tài)改變構造的功能。
為了最小化耦合度和促使耦合度可管理,OSGI技術提供了一種面向服務的架構,使組件動態(tài)地發(fā)現(xiàn)對方。
OSGI聯(lián)盟已經(jīng)開發(fā)了如HTTP服務器、配置、日志、安全、用戶管理、XML等很多公共功能標準組件接口。標準組件的兼容性插件實現(xiàn)可以從不同計算機服務提供商得到。
OSGi的主要職責就是為了讓開發(fā)者能夠創(chuàng)建動態(tài)化、模塊化的Java系統(tǒng)。
OSGI規(guī)范包括以下子規(guī)范:
A、Framework規(guī)范(OSGI核心,提供一個安全的可管理的Java Framework來部署可擴展的Java服務)
B、Package Admin Service規(guī)范(管理不同的Bundle之間的引用關系。當Bundle更新或者卸載時判斷是否有其它的服務正在使用當前的Bundle)
C、Start Level規(guī)范(定義了啟動和停止一個OSGi Service Platform時,不同的Bundles的啟動或者停止的先后順序)
D、Permission Admin Service規(guī)范(Bundle是否許可執(zhí)行另外的Bundle的代碼)
E、URL Handlers Service規(guī)范(怎樣注冊URL Schema,如何將java.io.InputStream對象轉(zhuǎn)換為特定的Java對象)
F、Log Service規(guī)范
G、Configuration Admin Service規(guī)范
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 Specfication
OSGI的優(yōu)勢主要表現(xiàn)在以下幾個方面:
A、熱插拔的插件體系結構
基于OSGI的應用程序可動態(tài)更改運行狀態(tài)和行為。在OSGI框架中,每一個組件都是可熱插拔的,因此,對某一特定的組件的修改并不會影響到容器中的所有組件,運行中的大部分組件依舊能照常工作,部署一個新的Bundle時也不需要重新啟動服務器。
B、可復用性
OSGI框架本身可復用性極強,易于構建真正面向接口的程序架構,每一個組件(Bundle)都是一個獨立可復用的單元?;贠SGI獨特的特性,進行企業(yè)開發(fā)的時候,對于新的開發(fā),可以從企業(yè)的組件庫中精簡出可復用的模塊,量身定做新的組件,大限度的利用了已有的資源,降低開發(fā)成本,增強企業(yè)的競爭力。
C、高效性,穩(wěn)定性
OSGI是一個穩(wěn)定而高效的系統(tǒng)。OSGI作為一個微核的系統(tǒng),其核心只有為數(shù)不多的幾個JAR包。基于OSGI框架的系統(tǒng)的低耦合性,其結構的優(yōu)勢性保證具體的某一個組件不至于影響到全局,更不會因為局部的錯誤導致全局系統(tǒng)的崩潰。
A、每個組件(Bundle)都由單獨的類加載器加載,與一些Java EE項目中使用比較多的框架整合比較困難,如Spring MVC、Struts2等。
B、目前OSGI框架提供的管理端不夠強大,現(xiàn)在的管理端中僅提供了基本的組件狀態(tài)管理、日志查看等功能,像動態(tài)修改系統(tǒng)級別的配置(config.ini)、動態(tài)修改組件的配置(Manifest.mf)、啟動級別等功能都尚未提供。
C、采用OSGI作為規(guī)范的模塊開發(fā)、部署方式自然給現(xiàn)有開發(fā)人員提出了新的要求,需要學習新的基于OSGI的開發(fā)方式。
OSGI框架從概念上可以分為三層:模塊層、生命周期層和服務層。
Module Layer:模塊層主要涉及包及共享的代碼;
Lifecycle Layer:生命周期層主要涉及組件的運行時生命周期管理;
Service Layer:服務層主要涉及模塊之間的交互和通信。
OSGI Framework是OSGI Service Platform規(guī)范的核心組成部分,提供了一個通用的、安全可管理的Java framework。通過OSGI Framework可以支持一種叫做組件的Service application的部署和擴展。
OSGI兼容設備可以下載并且安裝OSGI組件,也可一旦不再需要的時候刪除。組件安裝后會注冊一定數(shù)量的Services,并被由同一個Framework下的其它組件使用。
在一個動態(tài)擴展的的OSGI環(huán)境中,F(xiàn)ramework管理組件的安裝和更新,同時也管理組件和Services之間的依賴關系。
Framework提供給組件開發(fā)者必須的資源來在Java平臺上開發(fā),為開發(fā)的組件提供了代碼動態(tài)加載的功能, 也使得開發(fā)者開發(fā)、部署一個大規(guī)模的Services變的很容易。
其次,F(xiàn)ramework為Java組件開發(fā)者提供了簡明一致的編程模型,簡化了開發(fā)部署的復雜性。編程模型允許開發(fā)者將自己的接口規(guī)范綁定到OSGI環(huán)境中的Service。
一個一致的編程模型幫助開發(fā)者可以應付一些可估計的危急錯誤。Framework將會運行在不同的硬件環(huán)境上,但一致的接口確保組件可以運行在一致的服務接口上。
模塊層是OSGi框架中最基礎的部分。
OSGi的模塊化,是通過為Jar包添加metadata 來定義哪些類該暴露,哪些類該隱藏,其控制單元叫做組件Bundle(jar包)。?
Bundle是以jar包形式存在的一個模塊化物理單元,包含代碼、資源文件和元數(shù)據(jù)(metadata),并且jar包的物理邊界也是運行時邏輯模塊的封裝邊界。
Bundle是OSGi中的基本組件,其表現(xiàn)形式仍然為Java概念中傳統(tǒng)的Jar包。
通過META-INF目錄下的MANIFEST.MF文件對其予以進一步的定義。
通常一個MANIFEST.MF文件的內(nèi)容如下:
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的元數(shù)據(jù)。
元數(shù)據(jù)的內(nèi)容可以精確的定義Bundle的各種特征,同時能更好的對Bundle進行標識同時幫助用戶對Bundle進行理解。
生命周期層在OSGi框架中屬于模塊層上面的一層,生命周期層的運作是建立在模塊層的功能之上的。
生命周期層的主要功能是控制動態(tài)安裝、開啟、關閉、更新和卸載組件。
生命周期層能夠從外部管理應用或者建立能夠自我管理的應用(或者兩者的結合),并且給了應用本身很大的動態(tài)性。?
Bundle的使用需要生命周期層的API與OSGi框架的生命周期層進行交互。
OSGi服務是注冊到OSGi框架中的一個Java對象。注冊的時候可以設置Service的屬性。而在獲取Service的時候可以根據(jù)屬性進行過濾。
Bundle可以通過Bundle的上下文去注冊Service或去查詢Service。
模塊化是將一個大型系統(tǒng)分解為多個較小的互相協(xié)作的邏輯單元,通過強制設定模塊之間的邏輯邊界來改善系統(tǒng)的維護性和封裝性。
模塊(module)定義了一個邏輯邊界,模塊本身精確地控制哪些類是完全被封裝起來的,而哪些類需要暴露出來作為外部使用。開開發(fā)者可以輕松地將實現(xiàn)屏蔽在模塊的內(nèi)部,將公共API暴露在外部。
A、底層代碼的可見性控制
Java提供了private、public、protected和package private(無修飾符)四種訪問控制級別,提供了底層的OO數(shù)據(jù)封裝特性。Packege具有分割代碼的作用,但如果包中的代碼要對包外可見,必須設置為public(protected,使用繼承)。
org.serc.helloworld.Hello.java:定義了一個接口
package org.serc.helloworld;
public interface Hello {
void sayHello();
}
org.serc.helloworld.impl.HelloImpl.java:實現(xiàn)了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實現(xiàn)細節(jié)不應該暴露給其它包,但從Main.java的main方法中可以看出,為了創(chuàng)建Hello的實例,必須引入HelloImpl類,但是HelloImpl作為接口的實現(xiàn)細節(jié),不應該暴露給使用者,違反了封裝的原則。
如果不想讓HelloImpl暴露出來,需要做額外的工作保證既隱藏了實現(xiàn)細節(jié),又能簡單的創(chuàng)建一個實現(xiàn)了Hello接口的實例。可以通過多種方法(比如工廠模式)來實現(xiàn),但增加了與應用本身功能無關的多余工作,是Java的局限。
B、classpath的局限
在classpath中加入jar包的時候,只給出文件路徑,而jar包的版本、一致性、依賴性,無法在classpath中明確的設置或是從classpath中看出相應屬性。
classpath中的jar包是按序加載的,例如:
classpath=/servlet2.2/servlet.jar;/servlet2.3/servlet.jar, 在實際應用的過程中,Java使用servlet2.2,而不是servlet2.3。如果在大型系統(tǒng)中團隊分開開發(fā)時,各用各的servlet包,并且版本號不一樣,在最后將開發(fā)結果合并的時候,用的是哪個版本的servlet包就很難搞清楚。
即使classpath能注意到版本的問題,也沒法精確指出依賴。開發(fā)者需要根據(jù)提示信息增加依賴包,直到虛擬機不運行到缺包異常為止。
C、OSGI對JAVA局限的改善
OSGi中很好解決了JAVA的局限性:
包的可見性:OSGi通過引入包的可見性機制,能夠完全控制一個包中的代碼對哪些模塊可見,而不僅僅局限于無差別的可見性,從而完善了Java的代碼訪問控制機制。
包的版本:OSGi通過為包增加版本信息,可以精確控制代碼的依賴,保證代碼的版本一致性,彌補了classpath的缺點。
組件(bundle)是以jar包形式存在的一個模塊化物理單元,包含了代碼、資源文件和元數(shù)據(jù)(metadata),并且jar包的物理邊界也是運行時邏輯模塊的封裝邊界。
在標準的jar包的manifest文件中添加一些組件(bundle)的模塊化特征(metadata)后,jar包就變成了一個bundle。
bundle和普通jar包大的區(qū)別就在于元數(shù)據(jù)。
Bundle元數(shù)據(jù)的目的在于準確描述模塊化相關的bundle特征,讓OSGi框架對bundle進行各種處理工作(比如依賴解析,強制封裝等),元數(shù)據(jù)主要有三部分:
A、可讀信息(可選)
OSGi標準定義了幾個元數(shù)據(jù)條目幫助更好地理解和使用bundle,但所有的條目都不是必須的,并且不對模塊化特性產(chǎn)生任何的影響,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、代碼可見性(必須)
代碼可見性用于定義內(nèi)部與外部代碼。在JavaSE中的jar包如果放在classpath里,那么jar包對classpath下的所有程序都是可見的,并且可見性不能改變。而OSGi標準定義了如下的屬性用于描述代碼的可見性:
Bundle-ClassPath:定義了形成bundle的所有代碼所在的位置,Java 中的classpath是定義的jar包的位置,而Bundle-ClassPath屬性描述的是bundle內(nèi)部類在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框架中屬于模塊層上面的一層,其運作建立在模塊層的功能之上的。生命周期層主要功能是讓開發(fā)者能夠從外部管理應用或者建立能夠自我管理的應用(或者兩者的結合),并且給應用本身很大的動態(tài)性。
2、生命周期管理簡介一般來說,程序(或者程序的一部分)都一定服從某種生命周期。軟件的生命周期有4個典型的階段,如下:
如果正在創(chuàng)建一個應用,首先得安裝(install)應用;當應用的所有依賴都滿足,可以執(zhí)行應用;如果應用不再需要,可以停止(stop);一段時間后,可能需要更新(update)應用的版本;最終,可能會移除(remove)應用。
通過在外部或者內(nèi)部對應用進行操作,完成對應用的生命周期管理過程。對于非模塊化應用,操作是以整個應用為對象的;對于模塊化應用,可以有更細粒度(針對應用中的某個模塊)的生命周期管理。
要想使用組件(bundle),就得使用生命周期層的API與OSGi框架的生命周期層進行交互。
OSGi框架的核心并沒有強制使用任何特定的API交互機制(比如命令行,GUI,或者XML配置文件等),只是單純的Java API而已,開發(fā)者可以任意創(chuàng)造出自己想要的交互模式,保證了框架的靈活性。
在標準的Java編程中,會通過將jar包放到classpath中來使用jar包,而bundle不同。Bundle只有在被安裝(install)到一個OSGi框架的運行實例中才能用起來,并且OSGi框架支持對bundle完整的生命周期管理,并且支持這些管理操作在應用執(zhí)行完成,其動態(tài)性可見一斑。
Bundle生命周期的狀態(tài)轉(zhuǎn)移圖如下:
可以通過Bundle的getState方法來獲得bundle的當前狀態(tài)。
Starting和Stopping狀態(tài)是暫態(tài),在持續(xù)一會兒后就會自動轉(zhuǎn)移到下一個狀態(tài),不需要轉(zhuǎn)移條件。
生命周期層的API主要由BundleActivator、BundleContext、Bundle三個核心接口組成。
A、BundleActivator
BundleActivator讓開發(fā)者能夠捕捉bundle的start和stop事件,并對作出自定義的反應。
BundleActivator的接口定義如下:
public interface BundleActivator {
public void start(BundleContext context) throws Exception;
public void stop(Bundlecontext context) throws Exception;
}
如果一個類實現(xiàn)了BundleActivator接口,那么類就成為一個Activator。但有實現(xiàn)是不夠的,要讓OSGi框架知道Activator的存在。所以還需要在MANIFEST文件中添加如下一項屬性:Bundle-Activator:org.demo.Activator
當bundle啟動(start)的時候,OSGi框架就會調(diào)用Activator的start方法,同樣的也適用與stop方法。
并不是每個bundle都需要一個activator,有時候bundle只是為了和其它bundle分享代碼,而并不需要在啟動和停止的時候做出多余的動作。是否使用BundleActivator借口,需要具體問題具體分析。
B、BundleContext
BundleContext是bundle在框架中的執(zhí)行時上下文,提供了與框架進行交互的方法。
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來說都是唯一的執(zhí)行上下文,并且只有在bundle是屬于active狀態(tài)的時候執(zhí)行時上下文才是有意義的,即在start方法被調(diào)用和stop方法被調(diào)用的兩個時間點之間。如果一個bundle沒有處于active時間段,但組件的bundlecontext對象被使用,框架會拋出異常。
框架使用這個上下文對象還有一個目的就是為了bundle的安全和資源分配,所以BundleContext對象應該被當做私有對象,不應該被隨意在bundle之間傳遞。
C、Bundle
Bundle在邏輯上表示一個bundle,OSGi環(huán)境中的一個物理bundle對應一個bundle對象。bundle對象中包含了bundle的基本信息和bundle聲明周期的控制接口。
在BundleContext接口中,getBundle方法可以得到Bundle對象。
對于每個被安裝到框架中的bundle,框架都創(chuàng)建一個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框架的實現(xiàn)都是將locatioin解釋為指向OSGi bundle的一個URL,在需要的時候就會通過URL將bundle下載到框架中來安裝使用。但OSGi標準沒有規(guī)定location的形式必須是URL,而且URL也并不是非要不可的,還可以通過輸入流(Input Stream)來安裝bundle。
bundle不能自己改變自己的狀態(tài),比如說一個active的bundle不能stop自己,stop自己就會拋出異常。
服務是服務提供者和服務使用者之間的一個契約。使用者一般不關心服務實現(xiàn)的細節(jié),只關心是否滿足契約(服務應該提供什么功能,滿足什么格式)。使用服務的過程包含了發(fā)現(xiàn)服務和達成協(xié)議的形式,需要通過服務的標志性特征來找到對應的服務。
2、OSGI服務層服務層是OSGi框架中最上面的一層,服務層帶來了更多的動態(tài)性,并且使用了面向服務編程模型。當一個bundle發(fā)現(xiàn)開始使用OSGi中的一個服務后,服務可能在任何的時候改變或者是消失。
OSGi框架有一個中心化的注冊表,注冊表遵從publish-find-bind模型:
一個提供服務的bundle可以發(fā)布POJO作為服務的實體;一個使用服務的bundle可以通過注冊表找到和綁定服務。
可以通過BundleContext接口來完成服務的發(fā)布、發(fā)現(xiàn)、綁定,如下:
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);
}
3、發(fā)布服務為了讓其它bundle能發(fā)現(xiàn)服務,必須在發(fā)布服務前對其進行特征描述。服務特征包括接口的名字(可以是名字的數(shù)組),接口的實現(xiàn)和一個可選的java.util.Dictionary類型的元數(shù)據(jù)信息。示例如下:
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對象可以更新服務的元數(shù)據(jù):registration.setProperties(newMetadata);
可以直接將服務注銷:registration.unregister();
ServiceRegistration對象不能和其它Bundles共享,因為ServiceRegistration對象和發(fā)布服務的bundle的生命周期相互依存。如果bundle已經(jīng)不在框架執(zhí)行環(huán)境中存在,那么ServiceRegistration對象也不應該存在。
代碼中的參數(shù)new LSE()是一個POJO,不需要實現(xiàn)任何OSGi類型或者使用標注,只要滿足服務約定就可以。
如果在刪除發(fā)布的服務前bundle以及停止,框架會幫助刪除服務。
可以根據(jù)服務約定從注冊表中找到正確的服務。發(fā)現(xiàn)服務并獲得其引用的接口如下:
ServiceReference reference =
bundleContext.getServiceReference(StockListing.class.getName());
reference是服務對象的間接引用,不直接使用服務對象是為了將服務的使用和服務的實現(xiàn)進行解耦,將服務注冊表作為兩者的中間人,達到跟蹤和控制服務的目的,同時還可以在服務消失后通知使用者。
ServiceReference可以在bundle之間互享,與使用服務的bundle的生命周期無關。
在getServiceReference方法中,選擇service的默認優(yōu)先級是先選擇service.rank最高的,在rank相等的情況下選擇最早在框架中注冊的。除了默認的規(guī)則,還可以在getServiceReferences中通過添加過濾參數(shù)(作為調(diào)用該方法的第二個參數(shù))來做一些篩選。
ServiceReference[] references =
bundleContext.getServiceReferences(StockListing.class.getName(), “(&(currency=GBP)(objectClass=org.example.StockChart))”);
匹配參數(shù)是一個字符串,字符串的格式屬于LDAP查詢格式,在RFC1960標準中有完整的描述。
字符串中等號左邊的內(nèi)容是元數(shù)據(jù)(Dictionary)中的左值,通過左值對應的右值與服務的元數(shù)據(jù)進行匹配。匹配示例如下:
屬性匹配:
(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))
發(fā)現(xiàn)服務后,使用服務之前,必須從注冊表中綁定實現(xiàn)的服務。
StockListing listing =
(StockListing) bundleContext.getService(reference);
返回的POJO實例和在注冊表中注冊的實例是同一個。
每次使用getService方法的時候,注冊表會將對應服務的使用次數(shù)加1,同時會記錄誰在使用該服務。如果不想使用服務的,注銷服務。
bundleContext.ungetService(reference);
listing = null;
六、OSGI的實現(xiàn)
1、OSGI的具體實現(xiàn)OSGI是OSGi Alliance組織制定的Java模塊化規(guī)范,但OSGI聯(lián)盟并沒有給出OSGI容器的實現(xiàn),具體實現(xiàn)由第三方廠商完成,目前使用較多的OSGI容器有Apache Felix、Equinox、Spring DM。
2、OSGI的JAVA實現(xiàn)A、Apache Felix
Apache Felix是Apache旗下的一個OSGi框架,F(xiàn)elix是一個OSGi版本4規(guī)范的Apache實現(xiàn)。Apache Felix提供的服務幾乎涵蓋了全部的OSGi 4.2的標準,除此之外還提供了一些非標準的功能,例如iPOJO。Apache Felix框架本身非常緊湊,只需要3個包加一個shell就可以運行,無論是開發(fā)還是Debug都非常簡便。
B、Equinox
Equinox是Eclipse旗下的OSGi框架,本身也被Eclipse采用,是Eclipse的PDE開發(fā)環(huán)境的底層。Equinox本身也是相當?shù)娜娴目蚣?,提供的功能不比Felix少多少。Equinox被當做開發(fā)Eclipse Plugin的應用較多,如果要開發(fā)一個Web程序,就會感到功能和文檔不夠全面。Equinox大的優(yōu)勢在于和Eclipse結合緊密,只要安裝了PDE,就已經(jīng)有了Equinox,可以方便的在Eclipse里設置開發(fā)的Bundle,啟動、部署等操作也異常簡單,而且有專門的Debug界面。
C、Spring DM
Spring DM是Spring旗下的OSGi框架,Spring DM的大特點是結合了Spring框架。
D、Knopflerfish
Knopflerfish是OSGi的先行者,是一個相當標準OSGi框架,提供了絕大多數(shù)標準功能。
A、CTK Plugin Framework
CTK是基于Qt開發(fā)的支持生物醫(yī)學影像計算的開源項目。
CTK中的CTK Plugin Framework模塊借鑒了OSGI的思想,并實現(xiàn)了幾乎完整的OSGI框架API。
B、C++ Micro Services
C++ Micro Services是基于OSGI思想的用于創(chuàng)建和管理模塊化軟件系統(tǒng)的C++庫。
Apache Celix是基于C/C++的OSGI規(guī)范實現(xiàn),提供了一個使用組件和面向服務編程(SOP)開發(fā)模塊化應用的框架。
Apache Celix主要使用C語言開發(fā),為了支持C++,以庫的形式增加了抽象。
官方網(wǎng)站:http://celix.apache.org/
網(wǎng)站標題:架構設計——OSGI規(guī)范-創(chuàng)新互聯(lián)
轉(zhuǎn)載來源:http://jinyejixie.com/article42/pgdec.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供外貿(mào)建站、App開發(fā)、自適應網(wǎng)站、網(wǎng)站設計公司、云服務器、網(wǎng)站排名
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)