?该规范和核心部分是一个框架?,当中定义了应用程序的生命周期模式和服务注冊。基于这个框架定义了大量的OSGi服务:?日志、配置管理、偏好,HTTP(执行servlet)、XML分析、设备訪问、软件包管理、许可管理、星级、用户管理、IO连接、连线管理、Jini和?UPnP。
这个框架实现了一个优雅、完整和动态的php?
title=%E7%BB%84%E4%BB%B6%E6%A8%A1%E5%9E%8B&action=edit&redlink=1" title="组件模型(页面不存在)">组件模型。应用程序(称为bundle)无需又一次引导能够被远程安装、启动、升级和卸载(当中Java包/类的管理被具体定义)。
API中还定义了执行远程下载管理政策的生命周期管理。服务注冊同意bundles去检測新服务和取消的服务。然后对应配合。
OSGi原先关注于服务网关。事实上可用于多个方面。如今OSGi规范已经用于从移动电话到开源的Eclipse(当中包含了与IBM的OSGi框架SMF兼容的开源版本号)。?OSGi服务平台的应用包含:服务网关、?汽车、移动电话、?工业自己主动化、建筑物自己主动化、?PDA?网格计算、娱乐(如iPronto)、和?IDE。
OSGi规范是由成员通过公开的程序开发,对公众免费而且没有许可证限制。
可是OSGi?Alliance的兼容性程序仅仅对成员开放,眼下有12个兼容的实现。
2003年Eclipse选择OSGi作为其插件的底层执行时架构。Equinox?project对该理念进行了实验。2004年6月在Eclipse3?R3中公布。ProSyst是面向OSGi开发人员的Eclipse插件。
?
OSGI?里面有几个核心类:BundleContext,?Bundle,?ServiceRegistration,?ServiceReference
?
http://blog.csdn.net/teamlet/article/category/297017
关于OSGI的启动包含一个启动jar包和一个配置文件
Equinox\Configuration\Config.ini中放置的是启动信息
eclipse.ignoreApp=true
osgi.noShutdown=true
osgi.framework.activeThreadType=normal
osgi.bundles=./[email protected]:start,./[email protected]:start
?
Equinox\org.eclipse.osgi_3.5.0.v20090520.jar?
假设将该Jar放在在C盘osgi-dev下,那么在命令提示符下进入C:/osgi-dev?文件夹,执行以下命令:
>?java?-console?-jar?org.eclipse.osgi_3.3.1.R33x_v20070828.jar
几秒钟,osgi>提示符显示出来。
以下为一个sh脚本启动Osgi:
#!/bin/sh
#resl=`ps?-ef|grep?yuewang|grep?-v?grep`
resl=`ps?-ef|grep?org.eclipse.osgi_3.5.0.v20090520.jar|grep?-v?grep`
flag=0
for?i?in?$resl
do
??#echo?$i
??if?[?!?-z?$i?];?then
????flag=1
??fi
done
?
if?[?$flag?==?0?];?then
echo?"starting?SDMExpert"
cd?/etc/sdme
java?-Dlog4j.configuration=file:///etc/sdme/Properties/log4j.xml?-DSDMExpert.corbaTrace=off?
?????-Djacorb.connection.client.idle_timeout=600000?-Djacorb.connection.client.pending_reply_timeout=300000?
?-Djacorb.poa.queue_wait=on?-Djacorb.net.socket_factory.port.max=3000?
?-Dlogconsole?-jar?/usr/sdme/bin/org.eclipse.osgi_3.5.0.v20090520.jar?
?-configuration?/local/sdme/equinox?-clean?&
echo?"SDMExpert?started?now"
else
echo?"?sdmexpert?already?started"
fi
exit
?
?
?
可执行Java包
?
http://www.ibm.com/developerworks/cn/opensource/os-ecl-osgibdev/
OSGi?联盟建立于?1999?年,是一个非赢利机构。旨在建立一个开放的服务规范。
OSGi?规范为网络服务定义了一个标准的、面向组件的计算环境,它最初的目的就是为各种嵌入式设备提供通用的软件执行平台。屏蔽设备操作系统与硬件差别的中间件平台。通过这个平台。能够对不同软件商提供的应用(OSGi?中称为?Bundle)进行组件的生命周期管理的能力,如应用组件能够从执行中被安装、升级或者移除而不须要中断设备的操作,应用组件能够动态的发现和使用其它库或者应用程序。
因为?OSGi?技术具有服务组件模块化、动态载入应用等长处,正被越来越多的领域关注,如嵌入设备制造业、汽车制造业、企业应用等。眼下,OSGi?联盟公布的最新的?OSGi?服务规范为?4.0。读者能够查阅參考资料了解具体信息。
OSGi?的体系架构是基于插件式的软件结构,包含一个?OSGi?框架和一系列插件。在?OSGi中,插件称为?Bundle,当中,OSGi?框架规范是?OSGi?规范的核心部分,它提供了一个通用的、安全可管理的?Java?框架,通过这个框架。能够支持?Bundle?服务应用的部署和扩展。Bundle?之间能够通过?Import?Package?和?Require-Bundle?来共享?Java?类。在?OSGi?服务平台中。用户通过开发?Bundle?来提供须要的功能。这些?Bundle?能够动态载入和卸载,或者依据须要远程下载和升级。OSGi?体系结构图如图?1?所看到的:
当中:
Execution?Environment:
Bundle?应用所倚赖执行的?Java?执行环境。如?J2SE-1.4、CDC-1.0?等都是可用的执行环境。
Modules:
模块层定义了?Bundle?应用的载入策略。OSGi?框架是一个健壮而且严格定义的类载入模型。在大多数?Java?应用中。通常仅仅有一个单独的?ClassPath,它包含了全部的?Java?类文件和资源文件。OSGi基于Java技术。对于每一个实现了?BundleActivator?接口的?Bundle?应用,为它生成一个单独的?ClassLoader,使得?Bundle?应用的组织更加模块化。
Life?Cycle:
生命周期层能够动态地对?Bundle?进行安装(install)、启动(start)、停止(stop)、升级和卸载等操作。该层基于模块层。提供了一组?API?来控制?Bundle?应用的执行时操作。
Registers?the?specified?service?object?with?the?specified?properties?under?the?specified?class?names?into?the?Framework.?A?ServiceRegistration?object?is?returned.?The?ServiceRegistration?object?is?for?the?private?use?of?the?bundle?registering?the?service?and?should?not?be?shared?with?other?bundles.?The?registering?bundle?is?defined?to?be?the?context?bundle.?Other?bundles?can?locate?the?service?by?using?either?the
{getServiceReference}?method.
The?ServiceRegistration?object?may?be?used?to?update?the?properties?of?the?service?or?to?unregister?the?service.
Service?Registry?和?Services:
servR?=?context.registerService(IBundleInstallerService.class.getName(),?installer,?null);
servR.unregister();
?
?
为啥要使用ServiceRegistration和ServiceReference,我的观点是统一的接口进行管理和为了性能。使用Reference而不是对象本身,方面能够节省内存一方面能够提高性能。
BundleContext.registerService得到ServiceRegistration,通过ServiceRegistration的getReference得到ServiceReference。通过ServiceReference的getService得到对象本身。
注冊时使用的Properties文件的Properties信息来源于bundle中的Manifest.xml文件。
?
OSGi?服务层定义了一个集成在生命周期层中的动态协作模型,是一个公布、动态寻找、绑定的服务模型。一个服务一般是一个?Java?对象实现了特定的服务接口,而且通过服务注冊,被绑定到?OSGi?的执行环境中。
Bundle?应用能够注冊公布服务。动态绑定服务,而且在服务注冊状态改变时,能够接受到事件消息等。
Security:
OSGi?的安全管理是基于?Java2?安全体系的,贯穿在?OSGi?平台的全部层中。它能够对部署在?OSGi?执行环境中的?Bundle?应用进行具体的管理控制。
在一个动态扩展的?OSGi?环境中,OSGi?框架管理?Bundle?的安装和更新。同一时候也管理?Bundle?和服务之间的依赖关系。
一个?Bundle?可能处于以下六个状态,关于Bundle的生命周期能够通过Bundle.getState()方法得到。如图?2?所看到的:
INSTALLED:安装完毕,本地资源成功载入:?BundleContext.installBundle(location)方法,成功后返回一个bundle对象。
?
RESOLVED:依赖关系包含classpath及package满足。这个状态意味该Bundle要么已经准备好执行,要么是被停止了。体如今代码上例如以下:通过getBundlesRequirement方法得到全部bundle的BundleRequirement,这种方法中主要是对Require-Bundle里面的全部Bundle进行解析放到List中。再通过matchBundleAndRequirement对Bundle的依赖进行验证,满足后Bundle的状态就变为Resolved状态了。
private?HashMap<Bundle,?ArrayList<BundleRequirement>>?getBundlesRequirement(ArrayList<Bundle>?bundles)?{
HashMap<Bundle,?ArrayList<BundleRequirement>>?bundleTree?=?new?LinkedHashMap<Bundle,?ArrayList<BundleRequirement>>();
for?(Bundle?bdl?:?bundles)?{
ArrayList<BundleRequirement>?req?=?BundleUtil.getRequirement(bdl);
bundleTree.put(bdl,?req);
}
return?bundleTree;
}
public?HashMap<Bundle,?ArrayList<Bundle>>?matchBundleAndRequirement(HashMap<Bundle,?ArrayList<BundleRequirement>>?bundlesRequirement)?{
HashMap<Bundle,?ArrayList<Bundle>>?bundleTree?=?new?HashMap<Bundle,?ArrayList<Bundle>>();
for?(Bundle?key?:?bundlesRequirement.keySet())?{
ArrayList<BundleRequirement>?requirement?=?bundlesRequirement.get(key);
?
ArrayList<Bundle>?list?=?new?ArrayList<Bundle>();
for?(BundleRequirement?req?:?requirement)?{
for?(Bundle?candidate?:?bundlesRequirement.keySet())?{
if?(req.satisfyRequirement(candidate))?{
list.add(candidate);
}
}
}
bundleTree.put(key,?list);
}
return?bundleTree;
}
?
STARTING:Bundle正在被启动,BundleActivator的start()方法已经被调用可是还没有返回。
?
STOPPING:Bundle正在被停止,BundleActivator的stop()方法已经被调用可是还没有返回。
?
ACTIVE:Bundle?被成功启动而且在执行。
?
UNINSTALLED:bundle被卸载而且无法进入其它状态。
?
Bundle接口定义了getState()方法来返回Bundle的状态。
在?OSGi?平台之上。OSGi?联盟定义了非常多服务。服务是由一个?Java?Interface?来定义的。Bundle?能够实现这个接口而且把服务注冊到服务注冊表中去,用户能够从注冊表中找到须要的服务来使用,而且能够响应特定服务的状态改变,如服务注冊和服务取消。以下简介一下?OSGi?Release?4?的一些主要服务。OSGi?框架提供了权限管理服务,包管理服务和最初载入系统服务。这些服务是?OSGi?框架的一部分而且管理着?OSGi?框架的运作。
Permission?Admin?Service:权限管理是指?Bundle?是否许可其它的?Bundle?的代码。
当前的或者其它的?Bundle?的权限能够通过这个服务来操作,一旦被设定权限,立即就生效。
?Package?Admin?Service:Bundle?之间能够共享包内的?Java?类和资源,bundle?的更新可能须要?OSGi?框架又一次解析?Bundle?之间的依赖关系,这个服务提供了?OSGi?服务平台中包的共享状态信息。
Start?Level?Service:Start?Level是指一些在特定Bundle起动之前必须执行或者初始化的一系列?bundle。Start?Lever?Service?能够设置当前OSGi服务框架初始的Start?Level。而且能够指定和查询特定Bundle的Start?Level。
Equinox?框架是?Eclipse?组织基于?OSGi?Release?4?的一个实现框架,它实现了?OSGi?规范的核心框架和很多标准框架服务的实现。关于Equinox项目的具体信息,请查阅參考资料信息。在本文中,我们使用?Eclipse?3.2?平台开发两个基于?OSGi?的?Bundle?应用。当中第一个?Bundle?应用声明、实现并注冊了一个姓名查询服务,用于推断所给姓名是否在已定义的查询列表中;第二个?Bundle?应用查询并引用第一个?Bundle?应用所注冊的姓名查询服务,假设用户所给的姓名包含在查询列表中,将返回正确的信息。最后。将开发的?Bundle应用部署的?Equinox?OSGi?框架中。用户能够在?OSGi?控制命令行中输入命令来查询关于框架和?Bundle?应用的具体信息。读者能够从參考资料中获得本文?Bundle?应用的源码。
(1)创建?Plug-in?Project,在?Eclipse?3.2?开发环境中,从菜单条选择?File?>?New?>?Project...?,打开?New?Project?向导,能够看到有Plug-in?Project创建向导。创建一个Plug-in?项目。项目名为?example?的?Bundle?应用,该应用实现并注冊了一个姓名查询服务,实现了?BundleActivator?接口。选择?Equinox?框架作为?Bundle?应用执行的?OSGi?服务平台。
(2)实现OSGi服务通常须要两个步骤。首先定义所提供服务的接口,然后实现这个服务接口。在本例中,我们创建一个姓名查询服务用来查询所给姓名是否有效。首先定义姓名查询接口NameService.java。以下是该接口的源码:
package?example.service; /** ?*?A?simple?service?interface?that?defines?a?name?service. ?*?A?name?service?simply?verifies?the?existence?of?a?Name. **/ public?interface?NameService?{ /** ?????*?Check?for?the?existence?of?a?Name. ?????*[email protected]?name?the?Name?to?be?checked. ?????*[email protected]?true?if?the?Name?is?in?the?list, ?????*?????????false?otherwise. ????**/ public?boolean?checkName(String?name); } |
该服务接口非常easy,仅仅包含一个须要实现的方法。
为了将服务接口和服务实现相分离,方便其它?Bundle?引用该服务。我们通常须要将该服务接口单独放在一个包内,本例中,存放NameService.java?接口的?Java?包为?example.service。接下来,须要实现?NameService?接口,而且注冊该服务。在本例中,我们用内部类实现了该接口,以下是该?Bundle?应用的部分源码。
public?void?start(BundleContext?context)?throws?Exception?{ Properties?props?=?new?Properties(); props.put("ClassRoom",?"ClassOne"); context.registerService(NameService.class.getName(),?new?NameImpl(), props); } private?static?class?NameImpl?implements?NameService?{ //?The?set?of?names?contained?in?the?arrays. String[]?m_name?=?{?"Marry",?"John",?"David",?"Rachel",?"Ross"?}; /** ?*?Implements?NameService.checkName().?Determines?if?the?passed?name?is ?*?contained?in?the?Array. ?*? ?*[email protected]?name ?*????????????the?name?to?be?checked. ?*[email protected]?true?if?the?name?is?in?the?Array,?false?otherwise. ?*/ public?boolean?checkName(String?name)?{ //?This?is?very?inefficient for?(int?i?=?0;?i?<?m_name.length;?i++)?{ if?(m_name[i].equals(name))?{ return?true; } } return?false; } }? |
在start()方法中,利用BundleContext注冊一个姓名查询服务,而且为该服务设置相关属性以便服务查询。在实现姓名查询服务时。我们简单定义了一个静态数组用于存放有效的姓名信息。
(3)定义Bundle描写叙述文件MANIFEST.MF。Bundle应用example的MANIFEST.MF文件例如以下:
Manifest-Version:?1.0 Bundle-ManifestVersion:?2 Bundle-Name:?Example?Bundle Bundle-SymbolicName:?example Bundle-Version:?1.0.0 Bundle-Activator:?example.osgi.Activator Bundle-Localization:?plugin Import-Package:?org.osgi.framework;version="1.3.0" Export-Package:?example.service |
当中。Bundle-Activator属性指明了实现BundleActivator接口的类,该类用来启动和停止Bundle应用。
Export-Package属性指定了该Bundle输出的共享包,该属性能够使其它的Bundle应用引用我们所定义的服务接口。
(4)创建项目名为exampleClient的Bundle应用,该应用在OSGi平台上查寻并引用example?Bundle应用已经注冊的姓名查询服务,然后从标准输入读入用户所输入的姓名信息。推断所输入姓名是否有效。
exampleClient应用的部分源码例如以下。读者可从參考资料中获得完整源码。
public?void?start(BundleContext?context)?throws?Exception?{ ServiceReference[]?refs?=?context.getServiceReferences( NameService.class.getName(),?"(ClassRoom=*)"); if?(refs?!=?null)?{ try?{ System.out.println("Enter?a?blank?line?to?exit."); BufferedReader?in?=?new?BufferedReader(new?InputStreamReader( System.in)); String?name?=?""; //?Loop?endlessly. while?(true)?{ //?Ask?the?user?to?enter?a?name. System.out.print("Enter?a?Name:?"); name?=?in.readLine(); //?If?the?user?entered?a?blank?line,?then //?exit?the?loop. if?(name.length()?==?0)?{ break; } //?First,?get?a?name?service?and?then?check //?if?the?name?is?correct. NameService?nameservice?=?(NameService)?context .getService(refs[0]); if?(nameservice.checkName(name))?{ System.out.println("The?Name?is?Correct."); }?else?{ System.out.println("The?Name?is?Incorrect."); } //?Unget?the?name?service. context.ungetService(refs[0]); } }?catch?(IOException?ex)?{ } }?else?{ System.out.println("Couldn‘t?find?any?name?service..."); } } |
?
在Eclipse平台中,选择File-->Export...菜单,将开发的example和exampleClient两个Bundle应用导出成Jar文件,以便将它们部署到OSGi服务平台中。选择将要执行的Bundle应用,鼠标右键点击。在弹出菜单中。选择Run?AS-->Equinox?FrameWork来启动OSGi服务平台。
在Equinox启动配置控制台中。能够为Bundle应用设置默认的Start?Level和Bundle应用是否须要自己主动启动等选项。在本例中,为了解说怎样安装及启动Bundle应用,仅仅将example?Bundle应用设为自己主动启动。而exampleClient?Bundle应用须要我们用命令安装及启动。
当OSGi?Equinox?FrameWork启动后,在OSGi控制命令台中输入ss命令,能够查看OSGi服务平台中已经安装的Bundle应用信息及其状态。
如图4所看到的,能够看到当前OSGi服务平台中有两个Bundle处于Active状态,当中。system.bundle_3.2.0.v20060328为OSGi框架的系统Bundle,而example_1.0.0为注冊姓名查询服务的Bundle应用。1.0.0为Bundle应用的版本号号。
在OSGi控制命令台中利用install命令安装exampleClient?Bundle应用,用ss命令查看安装后的Bundle应用信息及其状态。
如图5所看到的:
在OSGi控制命令台中利用start命令安装exampleClient?Bundle应用,用户可输入姓名,利用姓名查询服务来推断所输入姓名是否有效。用ss命令查看启动后的Bundle应用信息及其状态。如图6所看到的:
用户在在OSGi控制命令台中,可利用stop命令来停止指定的Bundle应用。close命令用来停止并退出OSGi控制命令台。关于OSGi?Equinox?FrameWork控制台命令的具体信息。可查看參考资料。
OSGi服务框架提供了开放的、面向服务的、易于部署的编程模型,在构件面向服务为中心的企业应用的过程中。OSGi?技术正发挥越来越关键的数据。眼下。Eclipse?3.2?体系架构是參照OSGi实现的,Equinox框架是?Eclipse?组织基于OSGi?Release?4?的一个实现框架。它实现了OSGi?规范的核心框架和很多标准框架服务。
在本文中。我们利用Eclipse?平台开发了两个Bundle应用,而且在Bundle应用中,声明、实现、注冊并引用了一个简单的服务,最后,将Bundle应用部署到Equinox?OSGi服务框架中。
通过本文。读者能够了解怎样开发和部署基于OSGi规范的Bundle应用。
?