下面主要摘自IBM官方文档
https://www.ibm.com/developerworks/cn/education/opensource/os-eclipse-osgi/index.html
OSGi基础
OSGi的核心就在与类的加载和隔离。
bundle 中的类是如何查找的:
- 首先,它会找 JRE,这个很明显,这个实际是通过系统环境的 JAVA_HOME 中找到的,路径一般是 JAVA_HOME/lib/rt.jar、tools.jar 和 ext 目录,endorsed 目录。
- 其次,它会找 system bundle 导出的包(在Equinox平台内部的包)。
- 然后,它会找您的 import 的包,这个实际包含两种:一种是直接通过 require-bundle 的方式全部导入的,还有一种就是前面讲的通过 import package 方式导入的包。
- 查找它的 fragment bundle,如果有的话。
- 如果还没有找到,则会找自己的 classpath 路径(每个 bundle 都有自己的类路径)。
- 最后它会尝试根据 DynamicImport-Package 属性查找的引用。
下面是IBM提供的一个例子。每个Bundle在启动的时候,都会调用Activator。
package osgi.test.helloworld;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
public class Activator implements BundleActivator {
/*
* (non-Javadoc)
* @see org.osgi.framework.BundleActivator
* #start(org.osgi.framework.BundleContext)
*/
public void start(BundleContext context) throws Exception {
System.out.println("hello world");
}
/*
* (non-Javadoc)
* @see org.osgi.framework.BundleActivator
* #stop(org.osgi.framework.BundleContext)
*/
public void stop(BundleContext context) throws Exception {
}
}
在其的.MF文件中,比一般java应用,要多出如下字段
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可以有如下状态
INSTALLED 就是字面意思,表示这个 bundle 已经被成功的安装了
RESOLVED 很常见的一个状态,表示这个 bundle 已经成功的被解析(即所有依赖的类、资源都找到了),通常出现在启动前或者停止后
STARTING 字面意思,正在启动,但是还没有返回,所以您的 Activator 不要搞的太复杂
ACTIVE 活动的,这是我们最希望看到的状态,通常表示这个 bundle 已经启动成功,但是不意味着您的 bundle 提供的服务也是 OK 的
STOPPING 字面意思,正在停止,还没有返回
UNINSTALLED 卸载了,状态不能再发生变更了
一张经典的状态转化图如下
Equinox
简单来说Equinox,就是已经为你提供了若干bundle(system bundle)。
我们的 bundle 进入 Equinox 环境后,OSGi 框架对其做的事情如下:
- 读入 bundle 的 headers 信息,即 MANIFEST.MF 文件;
- 装载相关的类和资源;
- 解析依赖的包;
- 调用其 Activator 的 start 方法,启动它;
- 为其提供框架事件、服务事件等服务;
- 调用其 Activator 的 stop 方法,停止它;
一般基于OSGi的应用分成如下层次
通用第三方库层:这一层包括了常用的第三方库,例如 apache commons,jfreechart,xml 包等等,这一层需要将这些包全部 export 出去,这样上层就可以直接通过 require bundle 的方式使用这些包。
业务模型定义层:这一层依赖于(require-bundle)通用第三方库层,定义了应用的业务模型,例如各种 JavaBeans,也可以在这一层提供额外的应用统一配置服务,即为上层应用提供配置文件的管理服务。
业务逻辑实现层:这一层依赖于(require-bundle)通用第三方库层,还依赖于 (import package) 业务模型定义层提供的业务模型,定义了应用的业务逻辑,这一层可以细分为:
DAO(Database Access Object)服务层:即为上层应用提供数据库存取服务的层,其 export 出去的接口全部都是和数据库操作相关的;
Service 层:为 UI 层提供的业务逻辑的封装层,这样 UI 层只需要执行 service 层的接口即可,可以将更多的精力放在 UI 的设计;
展现维护层:这一层依赖于(require-bundle)通用第三方库层,和下面各层提供的管理服务接口,基于 HTTP 服务的方式提供应用的维护,例如配置文件的在线修改、服务的管理,bundle 的管理,日志的管理,内存的管理等等,这些都可以以“ RUNTIME ”的方式展现,管理员或者维护人员操作的就是 Equinox 运行环境。还可以实现大部分的操作不需要重启 JVM,这一点类似于 JMX。
事件服务:事件服务层是 OSGi 框架提供的标准服务之一,为除了通用第三方库层以外的各层提供事件服务,包括同步、异步的通知各种事件、发布各种事件等。通过事件服务,可以实现各层之间的联动。