OSGI原理和实现框架总结.docx
- 文档编号:8925913
- 上传时间:2023-02-02
- 格式:DOCX
- 页数:31
- 大小:1.24MB
OSGI原理和实现框架总结.docx
《OSGI原理和实现框架总结.docx》由会员分享,可在线阅读,更多相关《OSGI原理和实现框架总结.docx(31页珍藏版)》请在冰豆网上搜索。
OSGI原理和实现框架总结
OSGI原理和实现框架总结
V1.0.0
版本
编制修改/日期
审核/日期
批准/日期
备注
1.0.0
伏红平/2011-09-15
初稿
目录
OSGI原理和实现框架总结1
目录2
OSGI解读3
安全层:
3
模块层:
4
生命周期层:
6
服务层:
7
服务规范:
8
Equinox8
项目主页:
8
目前发布版本:
8
遵循标准:
9
Licenses9
下载:
9
开发和调试:
9
运行:
9
Felix9
项目主页:
9
目前发布版本:
9
遵循标准:
10
Licenses10
下载:
10
开发和调试:
10
运行:
10
文档:
10
其它:
10
Knopflerfish11
官方网站:
11
目前发布版本:
11
遵循标准:
11
License11
Knopflerfish3.X中包含的组件:
12
安装Knopflerfish12
运行Knopflerfish12
创建bundles13
例子:
两个数计算服务13
设置开发调试环境:
13
接口定义:
15
接口实现:
18
获取服务:
21
测试:
24
调试:
24
导出bundles:
25
部署到equinox:
26
部署到Felix:
27
部署到Knopflerfish:
28
个人总结:
29
参考资料:
29
OSGI解读
OSGI框架从功能上分为下面几个层次:
●安全层SecurityLayer
●模块层ModuleLayer
●生命周期层LifeCycleLayer
●服务接口层ServiceLayer
安全层:
OSGi安全层是OSGi服务框架的一个可选的层。
它基于Java2安全体系结构,提供了对精密控制环境下的应用部署和管理的基础架构。
OSGi服务平台采用两种方式对代码进行校验:
●位置验证
●签名验证
模块层:
ModuleLayer定义了在OSGI框架中是怎么去按照Module的思想去开发的。
框架定义了模型化单元,称之为一个bundle。
一个bundle由java的类和其他资源组成,可以为终端用户提供功能。
通过良好定义的方式,Bundle可以和导入(importer)及导出
(exporter)Bundle之间共享Java包。
在OSGi服务框架中,bundle是仅有的需要部署的Java应用实体。
Bundle以JAR文件的方式进行部署。
一个bundle是一个如下的JAR文件:
●拥有提供服务所必须的资源。
这些资源可以是java的class文件,或者是其他的数据如HTML文件,帮助文件,图标文件等。
一个bundleJAR文件也可以嵌入其他JAR文件作为资源,但是不支持多层嵌套的JAR。
●有一个manifest文件描述JAR文件内容和bundle的信息。
该文件处于JAR的头部,提供框架需要的安装和激活bundle所需的信息。
例如,它对其他资源如JAR文件的依赖这种状态信息必须在bundle运行之前加载。
●可以在OSGI-OPT文件夹提供可选的文档信息,该文件夹可以位于JAR文件根目录或者它的子文件夹中。
OSGI-OPT文件夹中的内容都是可选的。
例如,可以在其中保存
bundle的源代码。
管理系统可以删除该文件夹内容,以便于节约OSGi服务平台的存储空间。
当一个bundle开始运行,通过OSGi服务平台,它开始对安装在平台内的其他bundle提供功能和服务。
Bundle的描述信息在一个manifest文件中,在JAR文件中的META-INF目录下的MANIFEST.MF文件。
框架在manifest文件头中定义了Export-Package和Bundle-Classpath这样的OSGimanifest头,bundle的开发人员可以使用它们提供bundle的描述信息。
类加载机制:
许多bundle可以共享虚拟机(VM)。
在VM内部,bundle可以相互隐藏包和类,也可以和其他bundle共享包。
隔离和共享包关键是由java的类加载器来实现,类加载器通过仔细定义的规则从bundle空间的一个子集中加载类。
每一个bundle只会有一个单独的类加载器,类加载器形成了一个类加载的代理网络结构,如下所示:
类加载器可以加载类和资源,加载途径有:
●启动类路径:
启动类路径中有一个java.*的包以及它实现的包。
●框架类路径:
在框架中通常有一个单独的类加载器,加载框架实现的类和关键的服务接口类。
●Bundle类空间:
bundle的类空间由和bundle相关的JAR文件组成,以及其他和bundle紧密相关的JAR文件,比如bundle片断类空间是指一个给定的bundle类加载器可以访问到的所有的类。
因此,一个指定bundle的类空间来自:
●父类加载器(通常是来自启动类路径的java.*包中的)
●导入的包
●必须的bundle
●Bundle类路径(私有包)
●附加的片断
类空间必须是一致的,也就是说不能存在相同全名的两个类(为了防止类声明错误)。
但是,在OSGi框架中,不同的类空间可以存在同名的类。
在模块层,支持不同版本的类加载到相同的虚拟机中。
在使用一个bundle之前,框架必须对共享的包之间的约束关系进行解析。
解析过程就是确定导入包如何连接到导出包。
bundle的package共享机制
在开发中可以直接通过import-package方式来引用所需要的package。
通过export-package方式来导出对外暴露才包。
也可以在import-package中或者export-package中设置其过滤属性,以更加准确的获取或导出所需要的package。
可以通过版本过滤、元数据信息过滤、自定义属性过滤、必须的属性过滤来实现过滤获取或导出package。
生命周期层:
bundle可以处于以下状态中的一种:
●INSTALLED—成功安装bundle
●RESOLVED—所有bundle需要的Java类都准备好了。
这个状态标志着bundle已经是启动就绪或者是已经停止。
●STARTING—正在启动bundle。
调用了bundle激活器的start方法,而且还没有从方法中返回。
●ACTIVE—bundle已经启动完毕,正在运行中。
●STOPPING—正在停止bundle。
调用了bundle激活器的stop方法,而且还没有从方法中返回。
●UNINSTALLED—bundle已经卸载完毕,不能进入其他状态。
●安装Bundle
通过BundleContext的installBundle方法来安装Bundle,在安装前首先需要对Bundle进行校验,如校验通过,OSGI框架中将安装Bundle到系统中,此时OSGI框架会分配一个高于现在系统中所有的Bundle的ID给新的Bundle,安装完毕后Bundle的状态就变为INSTALLED了,同时会返回bundle对象,在Bundle安装后就要使用bundle对象来管理Bundle的生命周期状态了。
●解析Bundle
Bundle安装完毕后,OSGI框架将对Bundle进行解析,以检测Bundle中的类依赖等是否正确,如有错误则仍然处于INSTALLED状态,如成功Bundle的状态则转变为RESOLVED。
●启动Bundle
在启动Bundle前需检测Bundle的状态,如Bundle状态不为RESOLVED,那么需要先解析Bundle,如启动一个解析失败的Bundle,则会抛出BundleException,但此时Bundle的状态仍然会被设置为ACTIVE;如Bundle的状态已经是ACTIVE,那么启动Bundle对它不会产生任何影响。
通过BundleContext的getBundle方法可获取指定BundleID的Bundle对象,在获取到Bundle对象后可使用Bundle对象的start方法来启动Bundle,此时会调用MANIFEST.MF中的Bundle-Activator属性对应的BundleActivator类的start方法(如存在BundleActivator类),在start方法执行的过程中Bundle的状态为STARTING,当start方法执行完毕后Bundle的状态转变为ACTIVE,如start方法执行失败,Bundle的状态转变为RESOLVED。
●停止Bundle
通过BundleContext的getBundle方法可获取指定BundleID的Bundle对象,在获取到Bundle对象后可使用Bundle对象的stop方法来启动Bundle,此时会调用MANIFEST.MF中的Bundle-Activator属性对应的BundleActivator类的stop方法,在stop方法执行的过程中Bundle的状态为STOPPING,当stop方法执行完毕后Bundle的状态转变为RESOLVED,如stop方法执行失败,Bundle的状态则继续保留原状态。
即使Bundle已经停止,其export的package仍然是可以使用的,这也就意味着可以执行RESOLVED状态的Bundle中exportpackage的类。
●卸载Bundle
通过调用Bundle对象的uninstall方法可完成Bundle的卸载,此时Bundle的状态转变为UNINSTALLED。
即使Bundle已卸载,其export的package对于已经在使用的Bundle而言仍然是可用的,但对于新增的Bundle则不可使用已卸载的Bundleexport的package。
●监听Bundle的状态
在监听Bundle的状态上OSGI采用的是典型的Java中的事件机制,在OSGI中事件分为FrameworkEvent和BundleEvent两种,FrameworkEvent用于报告Framework已启动、改变了StartLevel、刷新了packages或是出现了错误;而BundleEvent则用于报告Bundle的生命周期的改变。
可通过实现BundleListener或SynchronousBundleListener来监听BundleEvent,可通过实现FrameworkListener来监听FrameworkEvent。
服务层:
ServiceLayer定义了Bundle动态协作的服务发布、查找和绑定模型,ServiceLayer
基于ModuleLayer和LifecycleLayer,使得OSGI形成了完整的动态模型。
不过ServiceLayer的定义比较简单,是一个典型的ServiceLocator模式的模型,
Service通过BundleContext完成注册和获取。
●服务的注册
可在任何时候通过BundleContext的registerService方法来完成服务的注册,和其他的服务框架一样,在OSGI中注册服务时也可以注册一个ServiceFactory的类,服务成功注册后会返回ServiceRegistration对象,通过这个对象的unregister方法可卸载服务。
●服务的获取
可在任何时刻通过BundleContext来获取服务,而通过BundleContext在需要的时候获取服务则可保证获取服务的动态性。
●服务的监听
通过实现ServiceListener可监听Service的状态,通过BundleContext注册监听器,在注册监听器时可增加过滤的属性,以更加准确的监听希望监听的服务的事件。
在OSGIR4中还推出了DeclarativeServices
DeclarativeServices提供了更好的服务注册、获取、监听等方式,使得其成为了OSGIR4中的重要角色,并由此替代了ServiceLayer。
DS提出了完整的Service-OrientedComponentModel(SOCM)概念,使得在Bundle
中可以按照Component+Service的方式进行开发。
Component和Service从定义上来看是差不多的,任何一个普通的Java对象都可以通过在配置文件中定义成Component,Component有下面这些作用:
●对外提供Service;
●使用其他Component提供的Service;
●交由OSGI框架管理生命周期。
通过配置文件可以把一个普通的Java对象定义为DS中的Component。
在DS中,服务的发布和获取都是通过配置文件完成。
服务的获取更像是spring中的IOC,在使用的时候由框架注入。
服务规范:
OSGI的server规范中定义了众多的服务,常用的服务:
●LogServer:
用于以日志方式记录系统操作。
●HttpServer:
要求至少实现servlet2.1规范便于开发人员基于此服务对外提供简单的http访问。
●ConfigurationAdminServer:
用于管理各bundle或其它OSGI服务的配置信息。
●DeclarativeServer:
可以实现DI方式的OSGI服务注入,并且是动态的。
●EventAdminServer:
用于实现事件方式的通知。
Equinox
项目主页:
http:
//www.eclipse.org/equinox/
目前发布版本:
3.7
2011.6.13
遵循标准:
OSGiRelease4,version4.2specification
实现了OSGI规范中所有方面。
Licenses
Eclipselicense
下载:
整个SDK,大概20M左右(压缩后),包含二进制文件和源码,不含文档。
官方文档提供的内容不多,基本是基于eclipse的在线文档和一些示例。
http:
//eclipse.org/equinox/documents/
开发和调试:
无需安装任何插件,直接用eclipse即可。
运行:
在外部可以使用命令行或者下载一个launcher来启动框架。
Felix
项目主页:
http:
//felix.apache.org/site/index.html
包含很多个子项目,并不是作为单个项目开开发
目前发布版本:
Framework3.2.2
2011.5.23
遵循标准:
OSGiRelease4,version4.2specification
Licenses
ApacheLicense,Version2.0
下载:
核心框架和其它子项目的jar包被分开,每个子项目的jar都需要单独下载。
核心框架总大小只几百K,轻量级框架。
开发和调试:
●安装eclipse插件
http:
//www.ops4j.org/pax/eclipse/update/
●在eclipse中新建工程,导入下载的源文件。
运行:
框架本身非常紧凑,你只需要3个包加一个shell就可以运行了
功能需要扩展则加入其它的jar包
文档:
官方文档和例子详细,包含用户文档和开发文档,社区非常活跃。
其它:
Felix在OBR,即OSGI的bundle仓库这一块做得非常非常好了。
这一块预计在OSGIV5中发布!
除了Felix,还有两个项目是和OSGi相关的。
一个是ApacheFelixKaraf,它本身是Felix的一个子项目,但他其实是封装了Felix提供更高一层的Runtime,例如提供了JAAS。
提供了Web控制台对加入其中的bundle进行管理!
另一个是ApacheAries,目前还处于起步阶段,它作为Felix的补充,提供OSGi企业级规范,包括JPA、JDBC、JTA、JNDI等等。
Karaf提供了bundle的运行环境。
还可以安装一个web控制台,使用浏览器进行控制
浏览器中的控制界面
Knopflerfish
官方网站:
http:
//www.knopflerfish.org/index.html
目前发布版本:
Knopflerfish3.2isreleased!
2011.7.15
遵循标准:
OSGiRelease4,version4.2specification.
License
BSDstylelicense.
Knopflerfish3.X中包含的组件:
KnopflerfishOSGiframework-OSGiR4v4.2CoreSpecificationimplementation
KnopflerfishOSGibundles-OSGiR4v4.2ServiceCompendiumimplementation
Knopflerfishcomponents&extras-Knopflerfishbundlesandutilities
ServiceCompendium部分没有完全实现。
安装Knopflerfish
至少java1.2.2
下载jar包直接运行即可解压得到,包含源代码,二进制文件,例子和文档。
框架默认属性设置在props.xargs文件中。
运行Knopflerfish
直接点击OSGI目录下framework.jar文件即可运行
或者使用命令行参数:
>cdosgi
>java-jarframework.jar
Knopflerfish提供了可视化操作界面
创建bundles
有三种方式创建我们自己的bundles
用Eclipse
用eclipse,需要安装eclipse插件
http:
//www.knopflerfish.org/eclipse-update/
详情参考:
KnopflerfishEclipsePlugin
用Ant
用Maven
实际开发中推荐使用eclipse插件,以便快速高效开发。
例子:
两个数计算服务
此示例开发调试环境基于eclipse3.5。
通过BundleContext在代码中注册和获取服务的方式不推荐使用,所以使用R4规范中的DS服务。
设置开发调试环境:
Run->runconfiguration
OSGIFramework哪里新建一个运行配置,选中右边Bundles标签,打开TargetPlatform,勾选住图中的4个bundles,其中的org.eclipse.equinox.ds为支持ds服务的bundle,另外的三个为框架运行所需bundle。
配置完成后点击run按钮,看到控制台输出如下信息表示环境配置成功。
输入ss
表示框架启动成功。
键入help可以得到帮助信息
接口定义:
在例子中,我们定义一个用于计算的接口
新建一个plug-in项目
使用标准OSGI框架
填写bundle相关的描述信息,注意,这里选择不生成Activator
点击finish,在src下面新建一个包ds.calculate,包中建一个接口Calculator
接口中只有一个方法:
packageds.calculate;
publicinterfaceCalculator
{
publicStringexcute(floatfirst,floatsecond);
}
打开META-INF文件夹下面的MANIFEST.MF文件
选择runtime,在ExportedPackages哪里导出刚才创建的包,不要忘了保存。
这时候可以查看源文件,里面包含了bundle相关信息,刚才的操作也反应到文件里
至此,我们完成了第一个bundle。
接下来我们实现这个接口。
接口实现:
新建一个plug-in项目,由于是使用DS,所以也不需要生成Activator。
这里实现一个加的操作。
完成后打开MANIFEST.MF文件,选择Dependencies,添加刚才的接口bundle。
注意保存。
新建包和类实现接口。
packageds.calculate.addserver;
importds.calculate.Calculator;
publicclassAddServerImpimplementsCalculator
{
@Override
publicStringexcute(floatfirst,floatsecond)
{
System.out.println("你正在使用加法服务:
");
returnString.valueOf(first+second);
}
}
新建文件夹OSGI-INF,在文件夹里新建文件
选中接口的实现类:
打开component.xml文件发布刚才的服务,注意这里使用的是接口。
查看源文件,类似于这个样子:
点击finish,这时候再来看MANIFEST.MF文件,多了一行:
获取服务:
新建一个plug-in项目,注意也不需要生成Activator
同样先导入必须的bundle,这里即为接口。
创建包和类来使用服务:
packageds.calculate.consumer;
importds.calculate.Calculator;
publicclassConsumer
{
privateCalculatorserver;
publicvoidprintNumber()
{
System.out.println(server.excute(10,20));
}
publicsynchronizedvoidsetServer(Calculatorserver)
{
this.server=server;
System.out.println("服务被设置!
!
");
System.out.println("使用服务!
!
");
printNumber();
}
publicsynchronizedvoidunsetServer(Calculatorserver)
{
if(this.server==server)
{
this.server=null;
}
System.out.println("服务被解设置!
!
");
}
}
新建文件夹OSGI-INF
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- OSGI 原理 实现 框架 总结