OSGi介绍(四)第一个bundle

5 篇文章 0 订阅

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

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的合作将会带来怎样的精彩效果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值