分类: Java
2009-06-19 19:05:56
过 于的一年多,在和很多it届的同学及朋友见面时,他们总会问我最近在做什么。“OSGi!”,我不加思索的回答。到目前为止,对这个单词得到的反应都没有 超出“这是什么?”,“我没有听说过”,“噢,能具体点吗?”等等。而我的回答更让他们糊涂,最后,大家干脆放弃这个话题,转到买房,运动等等更能体现聚 会实质的问题上。不过最近,我一直在思考这个问题,下次再遇到这种情况时,该如何去表达才能让也是it届的哥们姐们能迅速的理解这个领域的范围呢?要知 道,技术人员往往不善于表达,我们已经习惯了和业内人士用行话交流。
关于这个问题,我访问了OSGi
Alliance的网站,在里面的faqs中,找到了我想要的东西。实际上,正如faqs中所解答的,OSGi涵盖了太多的范围,简单的两三句话是无法说
清楚的。而我这里指的OSGi从技术的角度,应该说是“OSGi service platform ”,faqs中这样解释OSGi service
platform() :
The
OSGi service platform delivers an open, common architecture for service
providers, developers, software vendors, gateway operators and
equipment vendors to develop, deploy and manage services in a
coordinated fashion. .......(以下省略上千英文单词)
好长!不过第一句话就已经能总结陈词了,“OSGi service platform是一个开放并且提供统一接口标准的体系框架,基于这个体系框架,服务提供商,程序开发人员,软件提供商,服务网管运营商,设备提供商能够 协调地联合起来开发,部署以及管理向用户提供的各种服务。”还需要提到的是OSGi service platform是一个基于Java的platform。
OSGi的提出和诞生之初,其目的主要是能够灵活方便并远程管理互联的网络嵌入设备(听说是1997年左右提出,与Jini有深厚渊源)。随着硬件 设备的能力不断提高,java技术的日益普及,尤其J2ME的壮大,现实应用的需求也不断扩大和推进,一个统一的标准变得非常的必要。OSGi Alliance就在这样的背景下成立了。从1999年成立以来,OSGi Alliance已经针对这个service platform发布了4版规范,其中r4是2005年10月份刚刚发布。
目前有不少公司对OSGi service platform推出了自己的实现,象ibm的smf(Service Management Framework,嗯,多好的名字,在那么多的platform实现中,我个人最喜欢这个名字,言简意赅)。
德国的ProSyst公司()是OSGi Alliance中非常活跃的推动者,看看他们的产品列表吧(他们甚至提供了kvm + cldc的OSGi framework)
开源的Oscar()
对于OSGi的成功应用,最有名的应该是eclipse了,它就是基于OSGi service platform的产品。还有Apache,据说OSGi将被应用于其新一代的build工具中。这些都是j2se和j2ee的应用,而基于j2me的, 手机(对应OSGi Alliance的MEG)和车载设备(对应OSGi Alliance的VEG)是OSGi的主要领域,OSGi Alliance已经有相应的规范,这些领域的应用相信会更加精彩,让我们拭目以待吧。如何分析OSGi service platform的机制?给出几个硬生生的例子,然后分析一下
代码?那还不如你自己看书看规范好了。因此,我觉得还是结合一个应用实例来分析会更
容易理解,当然,是一个假想的应用实例。用怎样一个实例呢?嗯......
几个月前,一个中学同学打电话给我说他们要在PDA上开发一个简单的应用程序来临时纪
录工作的结果,并向我咨询,这种开发的难度和周期。这事启发我了,就以PDA的应用为
背景,让我们来假想一个场景,从而来比较传统的应用模型与采用OSGi的应用模型有怎样
的区别。
我这样想象:
小李是一个软件工程师,在一家专门为PDA开发应用程序和解决方案的公司工作。最近,
他刚为公司的一个客户开发完成了一套运行在PDA的JAVA应用程序,我们不要关心PDA是
什么硬件配置,只要知道它配备了JVM(cvm) + CDC以及PP和文件系统(呵呵设备还是比较
强劲的)。而这个客户是一个慈善机构,该机构人员携带PDA进入偏远山区收集生活困难
家庭的信息,以准备进行资助。而这套程序将会暂时把家庭信息保存在PDA中,并随时供
用户查询修改。用户使用一个月后,反馈非常好,但是,他们有新需求了,说原来只是想纪录
信息就成了,现在希望能给出一些排序功能,比如按家庭年收入对纪录进行排序.
接到这个需求,小李一看,这个简单,只要增加一个排序方法就可以了,让我们假设他使用了如下
数据结构来纪录家庭信息:
Class FamilyInfo {
private String familyName;//家庭名称
private int population; //人口数量
private int incomePerYear; //年收入
.(省略Getter和Setter方法)
}

为了满足这个需求,小李决定添加一个静态的排序方法:
public static FamilyInfo[] sortByIncomePerYear(FamilyInfo[] familyInfos){
//根据incomePerYear的值进行冒泡排序。
}
把相关连部分修改完毕后,小李重新制作了安装包和启动脚本,发送给客户,不管客户如何操作
总之,原来的PDA程序必须卸载,新程序必须拷贝到PDA上再次执行安装,重新启动运行。
又过了一阵,客户说,要求提供按人均年收入进行排序,然后同样的事情又发生了......
几个轮次下来,小李发现,客户的需求还在增加,他们可能要求增加一个字段,记录目前该
家庭得到的资助额,还可能添加按收入范围查询纪录等等,事情还远没有结束。
如何改进这个情况呢?当然,改进涉及多方面,比如从软件本身出发,可以使用合适的design
pattern重新设计程序的体系结构,使得程序更易于扩展,关于这一点,有太多的讨论了,我就不
掺和了。还有从部署方面说,配置,安装和卸载程序,对最终用户往往是一项mission impossible,
能否让应用程序自己升级,而用户只要点击一个"升级"来触发这个过程而已......
我想你当然知道我给的答案:OSGi,OSGi,OSGi!!!!
//需要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 {
}
}