Chasing an mobile web vision

          闖蕩在移動(dòng)互聯(lián)網(wǎng)的世界中

          OSGi介紹(四)第一個(gè)bundle

          先給出“扶貧助手”的第一種改造,我稱之為“直接型”,請(qǐng)看:

          package aa.bb.cc;
          //需要import osgi的核心package
          import org.osgi.framework.BundleActivator;
          import org.osgi.framework.BundleContext;
          //實(shí)現(xiàn)了BundleActivator
          public class FamilyInfo implements BundleActivator {
           
          private String familyName;
           
          private int population;
           
          private int incomePerYear;
           省略了getter和setter方法 
           
          public String toString() {
            
            
          return "Family: " + this.familyName + ", population: " + this.population + ", income: " + this.incomePerYear;
           }

           
           
          public int getIncomePerMember(){
            
          return (int)(this.incomePerYear/this.population);
           }

           
          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;
              }

             }

            }

            
            
           }

           
          //在framework每次啟動(dòng)該bundle的時(shí)候該方法會(huì)被framework調(diào)用執(zhí)行。
           public void start(BundleContext context) throws Exception {
            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());
            }

           }

           
          //在framework停止該bundle時(shí),該方法將被framework調(diào)用
           public void stop(BundleContext context) throws Exception {
           }

          }


          看到代碼的區(qū)別了嗎?我在不同之處都標(biāo)注了注釋。其實(shí),從說白了,就是實(shí)現(xiàn)了org.osgi.framework.BundleActivator這個(gè)接口。
          當(dāng)然,細(xì)心的話,你會(huì)發(fā)現(xiàn)這個(gè)bundle沒有public static void main(String[] args)方法了。那么它怎么被啟動(dòng)呢?這個(gè)就是bundle的奧秘所在。不過,如果你了解java的class loading機(jī)制以及reflection技術(shù),你立馬會(huì)明白這個(gè)bundle的運(yùn)行機(jī)制。這兩項(xiàng)技術(shù)廣泛應(yīng)用于j2ee(對(duì)吧?我得承認(rèn),j2ee的經(jīng)驗(yàn)不多,呵呵)以及java的plugin機(jī)制。
          簡(jiǎn)單說來(lái),java.lang.Class這個(gè)類有一個(gè)方法:
          public Object newInstance()throws InstantiationException,IllegalAccessException
          針對(duì)上面的“扶貧助手”bundle而言,framework只要通過ClassLoader找到aa.bb.cc.FamilyInfo.class并加載后,就可以通過newInstance()方法創(chuàng)建一個(gè)BundleActivator的實(shí)例,然后調(diào)用public void start(BundleContext context)方法,就完成了啟動(dòng)bundle的動(dòng)作了。之后,調(diào)用public
          void stop(BundleContext context)方法來(lái)停止bundle
          如果你接著問,framework怎么知道這個(gè)bundle里面的BundleActivator是哪個(gè)類呢?嗯,問到點(diǎn)子上了。這就涉及到下面我們要講的bundle的部署了。在上一篇給出的bundle定義中指出,Jar文件是bundle的唯一格式,也就是說,我們要運(yùn)行bundle,必須把代碼打成jar文件。而jar文件可以帶有manifest文件,這個(gè)文件對(duì)bundle是不可缺少的。OSGi規(guī)范里面,通過定義一系列適用于bundle的manifest關(guān)鍵字(bundle manifest header)來(lái)擴(kuò)展manifest文件。
          比如,開發(fā)人員在manifest中添加下面一行:
          Bundle-Activator: aa.bb.cc.FamilyInfo
          這樣,在bundle被部署到framework后,framework就可以通過讀取manifest的關(guān)鍵字來(lái)獲得BundleActivator的具體實(shí)現(xiàn)類名,并通過reflection機(jī)制產(chǎn)生BundleActivator的實(shí)例。
          這里就給出扶貧助手的manifest的一個(gè)例子:

          Manifest-Version: 1.0  
          Bundle-SymbolicName: aa.bb.cc.family //osgi specification 4強(qiáng)制要求的關(guān)鍵字,每個(gè)bundle都必須有唯一的symbolic name
          Bundle-Name: Family Info Manager        //bundle的名稱
          Bundle-Version: 
          1.0   //bundle的版本號(hào)
          Bundle-Activator: aa.bb.cc.FamilyInfo   //指明BundleActivator的實(shí)現(xiàn)類名
          Import-Package: org.osgi.framework
          ;version=1.3   //列出該bundle需要從其他bundle所引入的
                                                                               //package(s)(提供該package的bundle必須在其
                                                                               //manifest中有Export-Package: 
                                                                               //org.osgi.framework
          ;version=1.3)

          然后我們用jdk自帶的jar工具,來(lái)生成bundle jar文件。這樣,第一個(gè)bundle就完成了,您可以下載一個(gè)開源的framework安裝這個(gè)bundle試一試。在framework上嘗試對(duì)該bundle的啟動(dòng)和停止,輸出的結(jié)果應(yīng)該和原先的java application是一樣的,然后您還可以在那個(gè)start(context)的方法中,再增加一條記錄,重新打包,然后通過framework的update功能,就能夠在不重新啟動(dòng)framework的情況下升級(jí)該bundle,我就暫時(shí)偷懶不針對(duì)具體framework來(lái)給出操作的方法了,先給您自己先摸索了(當(dāng)然您也可以偷懶,因?yàn)楹竺嫖視?huì)結(jié)合具體framework深入講述的)。
          好了,說完代碼的改造,再看看改造所帶來(lái)的程序設(shè)計(jì)結(jié)構(gòu)變化:那~~~就~~~~是~~~~沒變化!因此我把這種原封不動(dòng)的改造方法稱為“直接型”,用這種直接法,我們可以輕易的把一個(gè)java應(yīng)用程序改造成bundle。而這種改造目前能看到的好處就是bundle的“熱”升級(jí)。那怎樣能更漂亮些呢?在下一篇中,我會(huì)進(jìn)一步改造這個(gè)扶貧助手成為兩個(gè)bundle,看看bundle的合作將會(huì)帶來(lái)怎樣的精彩效果

          posted on 2006-02-14 15:46 勤勞的蜜蜂 閱讀(5535) 評(píng)論(4)  編輯  收藏

          評(píng)論

          # re: OSGi介紹(四)第一個(gè)bundle 2007-06-21 17:38 hata

          精彩!我看完OSGI實(shí)戰(zhàn)都沒想過可以用這種方式生成bundle,輪廓更清晰了,加緊看下一篇,估計(jì)更爽!哇揀到寶咯~呵呵!謝謝大哥的資料!
          還問個(gè)問題啊,你網(wǎng)頁(yè)中的代碼可以“+”和“-”縮進(jìn)哦,是你自己做的吧?怎么實(shí)現(xiàn)的啊?在別的網(wǎng)都沒見過呢,只在IDE上用過,呵呵 :}  回復(fù)  更多評(píng)論   

          # re: OSGi介紹(四)第一個(gè)bundle 2008-01-18 23:40 風(fēng)學(xué)者

          兄弟,看到這里,不得不來(lái)給你獻(xiàn)花.寫的很精彩,也通俗易懂,給初學(xué)者很好的指導(dǎo).  回復(fù)  更多評(píng)論   

          # re: OSGi介紹(四)第一個(gè)bundle 2009-04-29 14:43 guest

          繼續(xù)

          我也正在研究,幫了不少忙,謝謝  回復(fù)  更多評(píng)論   

          # re: OSGi介紹(四)第一個(gè)bundle[未登錄] 2009-07-23 16:25 han

          我要轉(zhuǎn)載。。我要轉(zhuǎn)載。。。
          OSGI。。。。太誘人了。。  回復(fù)  更多評(píng)論   


          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 马龙县| 翼城县| 丘北县| 通道| 伊川县| 兴海县| 城固县| 江阴市| 文水县| 阿鲁科尔沁旗| 清丰县| 金溪县| 兴业县| 合江县| 从江县| 长岭县| 泾阳县| 新郑市| 枞阳县| 康平县| 临桂县| 麦盖提县| 潼南县| 沙湾县| 肇源县| 伊通| 鹿泉市| 富阳市| 大邑县| 肃南| 南开区| 泗阳县| 霍山县| 密山市| 桐乡市| 社会| 高碑店市| 五家渠市| 墨竹工卡县| 读书| 汉沽区|