OSGI:
OSGI的体系架构是基于插件式的软件结构,包括一个 OSGI 框架和一系列插件,在 OSGI中,插件称为 Bundle,其中,OSGI框架规范是OSGI规范的核心部分,它提供了一个通用的、安全可管理的 Java 框架,通过这个框架,可以支持 Bundle 服务应用的部署和扩展。Bundle 之间可以通过 Import Package 和 Require-Bundle 来共享 Java 类,在 OSGi 服务平台中,用户通过开发 Bundle 来提供需要的功能,这些 Bundle 可以动态加载和卸载,或者根据需要远程下载和升级
OSGI 架构图:
Bundle 应用所倚赖运行的 Java 执行环境,如 J2SE-1.4、CDC-1.0 等都是可用的执行环境。
Modules:
模块层定义了 Bundle 应用的加载策略。OSGi 框架是一个健壮并且严格定义的类加载模型。在大多数 Java 应用中,通常只有一个单独的 ClassPath,它包含了所有的 Java 类文件和资源文件,OSGi基于Java技术,对于每个实现了 BundleActivator 接口的 Bundle 应用,为它生成一个单独的 ClassLoader,使得 Bundle 应用的组织更加模块化。
Life Cycle:
生命周期层可以动态地对 Bundle 进行安装、启动、停止、升级和卸载等操作。该层基于模块层,提供了一组 API 来控制 Bundle 应用的运行时操作。
Service Registry 和 Services:
OSGi 服务层定义了一个集成在生命周期层中的动态协作模型,是一个发布、动态寻找、绑定的服务模型。一个服务通常是一个 Java 对象实现了特定的服务接口,并且通过服务注册,被绑定到 OSGi 的运行环境中。Bundle 应用可以注册发布服务,动态绑定服务,并且在服务注册状态改变时,可以接受到事件消息等。
Security:
OSGi 的安全管理是基于 Java2 安全体系的,贯穿在 OSGi 平台的所有层中,它能够对部署在 OSGi 运行环境中的 Bundle 应用进行详细的管理控制。
Bundle的组成:
1、MANIFEST.MF:描述了 bundle 的所有特征,包括名字、输出的类或者包,导入的类或者包,版本号等等。
2、代码:包括 Activator 类和其它一些接口以及实现,这个和普通的 Java 应用程序没有什么特殊的区别
3、资源:当然,一个应用程序不可能没有资源文件,比如图片、properties 文件、XML 文件等等,这些资源可以随 bundle 一起存在,也可以以 fragment bundle 的方式加入
OSGI中的Bundle:
Bundle可以通过export的方式向OSGI容器中的其他Bundle公开自己Bundle中的包,包含模型,接口类等。
也可以通过import方式将OSGI容器中其他Bundle导出的包进行引入。
Bundle也可以定义扩展点,也可以实现其他Bundle公布的扩展点。
MANIFEST.MF
manifest.mf是用于描述Bundle信息的文件,通常位于/META-INF/目录下
属性名字 | 含义 |
Bundle-Activator |
Bundle 的启动器 |
Bundle-SymbolicName |
名称,一般使用类似于 JAVA 包路径的名字命名 |
Bundle-Version |
版本,注意不同版本的同名 bundle 可以同时上线部署 |
Export-Package |
导出的 package 声明,其它的 bundle 可以直接引用 |
Import-Package |
导入的 package |
Eclipse-LazyStart |
是否只有当被引用了才启动 |
Require-Bundle |
全依赖的 bundle,不推荐 |
Bundle-ClassPath |
本 bundle 的 class path,可以包含其它一些资源路径 |
Bundle-RequiredExecutionEnvironment |
本 bundle 必须的执行环境,例如 jdk 版本声明 |
Bundle生命周期管理:
Bundle的状态变迁图:
状态名字 | 含义 |
INSTALLED |
就是字面意思,表示这个 bundle 已经被成功的安装了 |
RESOLVED |
很常见的一个状态,表示这个 bundle 已经成功的被解析(即所有依赖的类、资源都找到了),通常出现在启动前或者停止后 |
STARTING |
字面意思,正在启动,但是还没有返回,所以您的 Activator 不要搞的太复杂 |
ACTIVE |
活动的,这是我们最希望看到的状态,通常表示这个 bundle 已经启动成功,但是不意味着您的 bundle 提供的服务也是 OK 的 |
STOPPING |
字面意思,正在停止,还没有返回 |
UNINSTALLED |
卸载了,状态不能再发生变更了 |
Bundle的运行以来OSGI平台为其提供的Classloader,由classloader负责查找装载该Bundle运行所依赖(Require-Bundle )和导入(Import-Packag)的包以及该Bundle本身。
Bundle的ClassLoader
Bundle的Classloader能加载的所有类的集合构成了Bundle的类空间(Class Space)。该类弓箭包含的类资源主要有以下方面:
1、父ClassLoader可加载的类集合
2、Import-Package定义的导入的包
3、Require-Bundle定义的依赖的Bundle的类集合;
4、Bundle自身的类集合,通常在Bundle-Classpath中定义
5、属于该Bundle的Fragment类集合。
在实际运行环境中,Bundle 的 Class Loader 根据如下规则去搜索类资源。规则简要介绍如下:
1、如类资源属于 java.* 包,则将加载请求委托给父加载器(所有Bundle都有共同的Parent ClassLoader)
2、如类资源定义在OSGI框架的启动委托列表(org.osgi.framework.bootdelegation)中,则将加载请求委托给父加载器
3、如类资源属于在 Import-Package 中定义的包,则框架通过 Class Loader 依赖关系图找到导出此包的 Bundle 的 Class Loader,并将加载请求委托给此 Class Loader ;
4、如类资源属于在 Require-Bundle 中定义的 Bundle,则框架通过 Class Loader 依赖关系图找到此 Bundle 的 Class Loader,将加载请求委托给此 Class Loader ;
5、Bundle 搜索自己的类资源 ( 包括 Bundle-Classpath 里面定义的类路径和属于 Bundle 的 Fragment 的类资源);
6、若类在 DynamicImport-Package 中定义,则开始尝试在运行环境中寻找符合条件的 Bundle 。
如果在经过上面一系列步骤后,仍然没有正确地加载到类资源,则 OSGi 框架会向外抛出类未 发现异常
参考:
探索OSGI框架的组件运行机制:http://www.ibm.com/developerworks/cn/java/j-lo-osgi/
使用Equniox开发OSGI应用程序:http://www.ibm.com/developerworks/cn/education/opensource/os-eclipse-osgi/index.html