先讓我們來看看OSGi service platform的體系結(jié)構(gòu)。另外要說明的是,我在后面的文章中,將采用framework來代替OSGi service platfrom,這樣比較簡便。 下面這張圖來自O(shè)SGi Alliance的主頁(http://www.osgi.org/)
層次很分明吧。放到我們假想的案例中,OS&Hardware可以對應(yīng)為PDA的硬件和操作系統(tǒng),您可以想象它是Intel xscacle + Microsoft window mobile,或者是Arm + embedded Linux 而Execution Environment當(dāng)然是我們上次提到的CVM + CDC + FP + PP,有這個(gè)jvm的配置運(yùn)行framework就綽綽有余了。而再往上,就是我們要重點(diǎn)學(xué)習(xí)和分析的OSGi framework了。而Modules, Life Cycle, Service Registry, Services和Security是從不同的5個(gè)角度來劃分framework所具備的功能,后面我將會從除了Security外的四個(gè)方面分別結(jié)合我們的假設(shè)場景來分析。而體系結(jié)構(gòu)的最上層是符合OSGi framework接口標(biāo)準(zhǔn)的應(yīng)用程序,也就是OSGi世界中有名的“bundle”。
下面來看看OSGi規(guī)范是如何定義一個(gè)bundle的。在r4規(guī)范的第27頁中大致這樣描述到:Framework定義了模塊(modularization)的單元,叫作bundle。Bundle實(shí)際就是一個(gè)具有jar(Java ARchive)格式的文件,其中包含了java的class文件和其他資源文件(比如圖標(biāo),配置文件等等)。Bundle可以在自己的manifest文件中說明自己能夠提供哪些java包,其他bundle如果在自己的manifest文件中指定了它需要這個(gè)包,那他們之間就可能產(chǎn)生java包的依賴關(guān)系,這樣多個(gè)bundle之間就可以共享java包。值得注意的是,bundle是能夠在framework中部署的唯一格式。下面給出原文的描述: A bundle is a JAR file that: ? Contains the resources necessary to provide some functionality. These resources may be class files for the Java programming language, as well as other data such as HTML files, help files, icons, and so on. A bundle JAR file can also embed additional JAR files that are available as resources and classes. This is however not recursive. ? Contains a manifest file describing the contents of the JAR file and providing information about the bundle. This file uses headers to specify information that the Framework needs to install correctly and activate a bundle. For example, it states dependencies on other resources, such as Java packages, that must be available to the bundle before it can run. ? Can contain optional documentation in the OSGI-OPT directory of the JAR file or one of its sub-directories. Any information in this directory is optional. For example, the OSGI-OPT directory is useful to store the source code of a bundle. Management systems may remove this information to save storage space in the OSGi Service Platform.
framework的modules這一方面功能將主要負(fù)責(zé)bundle的安裝部署,更新和卸載,以及bundle在設(shè)備的物理存儲(如果有的話)。在這個(gè)層次,每個(gè)bundle都是獨(dú)立的,它的安裝,升級和卸載完全不依賴任何其他bundle,這點(diǎn)framework提供了強(qiáng)大的隔離性。Life Cycle專門負(fù)責(zé)對bundle的解析(比如關(guān)聯(lián)兩個(gè)有相互依賴關(guān)系的bundle),啟動(相當(dāng)于運(yùn)行應(yīng)用程序)和停止(相當(dāng)于停止應(yīng)用程序)。這個(gè)層次中,bundle間的邏輯關(guān)系被創(chuàng)建起來,這些關(guān)系能否成功的創(chuàng)建,將會直接影響bundle的成功解析和啟動。Service Registry可以認(rèn)為是一個(gè)數(shù)據(jù)庫,bundle啟動后,可以向這個(gè)數(shù)據(jù)庫注冊它動態(tài)提供的服務(wù)。只要bundle不被停止,且bundle不主動撤銷注冊的服務(wù),這個(gè)服務(wù)將一直保存在這個(gè)數(shù)據(jù)庫中供其它bundle來查詢和使用。而Services就是由bundle運(yùn)行時(shí)提供的具體服務(wù)對象,這些服務(wù)對象的存在,使得framework具有極其動態(tài)的特征,并為framework運(yùn)行時(shí)提供靈活強(qiáng)大的功能。 另外,根據(jù)OSGi Alliance的說法,OSGi的運(yùn)行平臺包括了j2me(kvm + cldc + midp, cvm + cdc+fp), j2se, j2ee。不過,我個(gè)人還是覺得目前的midp規(guī)范還太弱,OSGi要想運(yùn)行在上面,很多功能實(shí)現(xiàn)起來都比較不爽。
好,有了對framework結(jié)構(gòu)層次的皮毛認(rèn)識,下面我們就開始著手改造那個(gè)“扶貧助手”的程序,使其變成OSGi的bundle(s),然后從上面提到的4個(gè)方面來分析framework的機(jī)制。 這里,我先給出“扶貧助手”的java application模擬程序代碼:
package aa.bb.cc;

 public class FamilyInfo {
private String familyName; //家庭名稱
private int population; //人口數(shù)量
private int incomePerYear; //家庭年收入

…..//省略了getter和setter方法

//獲得家庭人均年收入
 public int getIncomePerMember() {
return (int)(this.incomePerYear/this.population);
}

 public String toString() {
return "Family: " + this.familyName + ", population: " + this.population + ", income: " + this.incomePerYear;
}
//按家庭年收入又低到高排序
 public static void sortByIncomePerYear(FamilyInfo[] families) {
FamilyInfo temp = null;
 for(int i = 0; i < families.length -1; i ++) {
 for(int j = i + 1; j < families.length; j ++) {
 if(families[i].getIncomePerYear() > families[j].getIncomePerYear()) {
temp = families[i];
families[i] = families[j];
families[j] = temp;
}
}
}
}

//按家庭人均年收入由低到高排序
 public static void sortByIncomePerMember(FamilyInfo[] families) {
FamilyInfo temp = null;
 for(int i = 0; i < families.length -1; i ++) {
 for(int j = i + 1; j < families.length; j ++) {
 if(families[i].getIncomePerMember() > families[j].getIncomePerMember()) {
temp = families[i];
families[i] = families[j];
families[j] = temp;
}
}
}
}

 public static void main(String[] args) {
FamilyInfo[] families = new FamilyInfo[3];
families[0] = new FamilyInfo();
families[0].setFamilyName("Zhang");
families[0].setPopulation(3);
families[0].setIncomePerYear(1200);
families[1] = new FamilyInfo();
families[1].setFamilyName("Li");
families[1].setPopulation(6);
families[1].setIncomePerYear(1800);
families[2] = new FamilyInfo();
families[2].setFamilyName("Liu");
families[2].setPopulation(4);
families[2].setIncomePerYear(1500);
FamilyInfo.sortByIncomePerYear(families);
 for(int i = 0; i < families.length; i ++) {
System.out.println(families[i].toString());
}
FamilyInfo.sortByIncomePerMember(families);
 for(int i = 0; i < families.length; i ++) {
System.out.println(families[i].toString());
}
}
}


|