Chasing an mobile web vision

闯荡在移动互联网的世界中

OSGi介绍(四)第一个bundle

先给出“扶贫助手”的第一种改造,我称之为“直接型”,请看:

package aa.bb.cc;
//需要import osgi的核心package
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
//实现了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每次启动该bundle的时候该方法会被framework调用执行。
 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时,该方法将被framework调用
 public void stop(BundleContext context) throws Exception {
 }

}


看到代码的区别了吗?我在不同之处都标注了注释。其实,从说白了,就是实现了org.osgi.framework.BundleActivator这个接口。
当然,细心的话,你会发现这个bundle没有public static void main(String[] args)方法了。那么它怎么被启动呢?这个就是bundle的奥秘所在。不过,如果你了解java的class loading机制以及reflection技术,你立马会明白这个bundle的运行机制。这两项技术广泛应用于j2ee(对吧?我得承认,j2ee的经验不多,呵呵)以及java的plugin机制。
简单说来,java.lang.Class这个类有一个方法:
public Object newInstance()throws InstantiationException,IllegalAccessException
针对上面的“扶贫助手”bundle而言,framework只要通过ClassLoader找到aa.bb.cc.FamilyInfo.class并加载后,就可以通过newInstance()方法创建一个BundleActivator的实例,然后调用public void start(BundleContext context)方法,就完成了启动bundle的动作了。之后,调用public
void stop(BundleContext context)方法来停止bundle
如果你接着问,framework怎么知道这个bundle里面的BundleActivator是哪个类呢?嗯,问到点子上了。这就涉及到下面我们要讲的bundle的部署了。在上一篇给出的bundle定义中指出,Jar文件是bundle的唯一格式,也就是说,我们要运行bundle,必须把代码打成jar文件。而jar文件可以带有manifest文件,这个文件对bundle是不可缺少的。OSGi规范里面,通过定义一系列适用于bundle的manifest关键字(bundle manifest header)来扩展manifest文件。
比如,开发人员在manifest中添加下面一行:
Bundle-Activator: aa.bb.cc.FamilyInfo
这样,在bundle被部署到framework后,framework就可以通过读取manifest的关键字来获得BundleActivator的具体实现类名,并通过reflection机制产生BundleActivator的实例。
这里就给出扶贫助手的manifest的一个例子:

Manifest-Version: 1.0  
Bundle-SymbolicName: aa.bb.cc.family //osgi specification 4强制要求的关键字,每个bundle都必须有唯一的symbolic name
Bundle-Name: Family Info Manager        //bundle的名称
Bundle-Version: 
1.0   //bundle的版本号
Bundle-Activator: aa.bb.cc.FamilyInfo   //指明BundleActivator的实现类名
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工具,来生成bundle jar文件。这样,第一个bundle就完成了,您可以下载一个开源的framework安装这个bundle试一试。在framework上尝试对该bundle的启动和停止,输出的结果应该和原先的java application是一样的,然后您还可以在那个start(context)的方法中,再增加一条记录,重新打包,然后通过framework的update功能,就能够在不重新启动framework的情况下升级该bundle,我就暂时偷懒不针对具体framework来给出操作的方法了,先给您自己先摸索了(当然您也可以偷懒,因为后面我会结合具体framework深入讲述的)。
好了,说完代码的改造,再看看改造所带来的程序设计结构变化:那~~~就~~~~是~~~~没变化!因此我把这种原封不动的改造方法称为“直接型”,用这种直接法,我们可以轻易的把一个java应用程序改造成bundle。而这种改造目前能看到的好处就是bundle的“热”升级。那怎样能更漂亮些呢?在下一篇中,我会进一步改造这个扶贫助手成为两个bundle,看看bundle的合作将会带来怎样的精彩效果

posted on 2006-02-14 15:46 勤劳的蜜蜂 阅读(5503) 评论(4)  编辑  收藏

评论

# re: OSGi介绍(四)第一个bundle 2007-06-21 17:38 hata

精彩!我看完OSGI实战都没想过可以用这种方式生成bundle,轮廓更清晰了,加紧看下一篇,估计更爽!哇拣到宝咯~呵呵!谢谢大哥的资料!
还问个问题啊,你网页中的代码可以“+”和“-”缩进哦,是你自己做的吧?怎么实现的啊?在别的网都没见过呢,只在IDE上用过,呵呵 :}  回复  更多评论   

# re: OSGi介绍(四)第一个bundle 2008-01-18 23:40 风学者

兄弟,看到这里,不得不来给你献花.写的很精彩,也通俗易懂,给初学者很好的指导.  回复  更多评论   

# re: OSGi介绍(四)第一个bundle 2009-04-29 14:43 guest

继续

我也正在研究,帮了不少忙,谢谢  回复  更多评论   

# re: OSGi介绍(四)第一个bundle[未登录] 2009-07-23 16:25 han

我要转载。。我要转载。。。
OSGI。。。。太诱人了。。  回复  更多评论   


只有注册用户登录后才能发表评论。


网站导航: