OSGi(Open Service Gateway initiative)
- 其英文定义为:The Dynamic Module System for Java ,由此可见,OSGi的主要职责就是为了让开发者能够构建动态化、模块化的Java系统。使用OSGi,系统的各个组件就像插件一样,暴露特定的接口,实现“即插即用”。
OSGI特点
- 从需求实现方面,OSGI 为动态扩充、修改系统功能和改变系统行为提供了支撑
从部署和运行的角度来说,OSGi的特点就更多了,OSGi的动态化很大程度体现在系统的部署和运行时。这些特点包括:
- 切合真实运行环境:OSGi框架是动态的,bundle能够进行即时的更新,服务可以根据需要动态增加或者删除。比如一个服务可以是一个网络中的设备,如果一个设备被监测到,则服务可以动态注册;如果设备被移除,则服务能够动态注销。在这样的运行环境中编程将需要耗费大量的开销来处理动态性,但是OSGi帮助开发者处理了绝大多数动态性方面的工作。
- 易于部署:OSGi定义了组件是如何安装和管理的,标准化的管理API使得OSGi能够和现有和将来的各种系统有机的集成。
- 动态更新:这是OSGi被最经常提起的一个特性,即所谓的“热插拔”特性,bundle能够动态的安装、启动、停止、更新和卸载,而整个系统无需重启。
- 适配性:这主要得益于OSGi提供的服务机制、组件可以动态的注册、获取和监听服务,使得系统能够在OSGi环境调整自己的功能。
- 透明:提供了管理API来访问内部状态,因此通常无需去查看日志,能够通过命令行进行调试。
- 版本化:bundle可以版本化,多版本能够共存而不会影响系统功能,解决了JAR hell的问题。(这在开发时也提供了很大的帮助)
- 快速:这得益于OSGi的类加载机制,和JAR包的线性加载不同,bundle委托式的类加载机制,使得类的加载无需进行搜索,这又能有效的加快系统的启动速度。
- 懒加载:OSGi技术采用了很多懒加载机制。比如服务可以被注册,但是直到被使用时才创建。
从开发的角度来说,OSGi具有以下特点:
- 复杂性的降低:基于OSGi的组件模型bundle能够隐藏内部实现,bundle基于服务进行交互。
- 复用:很多第三方的组件可以以bundle的形式进行复用。
- 简单:核心的API总过包括不超过30个类和接口。
- 小巧:OSGi R4框架的实现仅需要300KB的JAR file就足够。在系统中引入OSGi几乎没有什么开销。
- 非侵入式:服务可以以POJO的形式实现,不需要关注特定的接口。
OSGI思想:强调微核+系统插件+应用 插件的概念
OSGI框架
OSGi框架提供了一个通用安全可管理的Java框架,能够支持可扩展可下载的应用(即bundles)的部署。OSGi框架是OSGi技术最基础也是最核心的部分。OSGi框架分为以下几层,如下图所示:
- 安全层
- 模块层
- 生命周期层
- 服务层
- 服务
Equinox为Eclipse的OSGI框架
- Oscar 是一个遵循 OSGI R3 框架的实现
- Knopflerfish 实现了 OSGI R4,也提供了为方便开发基于 OSGI 系 统的大量的 Bundle。
OSGI的构件
- Bundle其实就是一个jar文件,这个jar文件和普通的jar文件唯一不同的地方就是 Meta-inf目录下的MANIFEST.MF文件的内容,可以称它为bundle的元数据。信息中包 含有象Bundle的名称、描述、开发商、classpath、需要导入的包以及输出的包等等。
- JAR包的限制:
- JAR 包通过类路径环境变量解析,而这并未提供管理 JAR 依赖关系的可靠框架。
- JAR 无法进行版本控制,因此无法跟踪所创建或修改的 JAR 包的历史。
- 没有用于在运行时出现代码更改的情况下动态更新 JAR 文件的框架。
- Bundle 通过实现 BundleActivator 接口去控制其生命周期。在 Activator 中编写 Bundle 启动、停止时所需要进行的工作,同时也可以在 Activator 中发布或者监听框架的事件 状态信息,以根据框架的运行状态做出相应的调整。
- JAR包的限制:
生命周期层
Bundle具有如下几个状态:INSTALLED, RESOLVED,STARTING, ACTIVE, STOPPING, UNINSTALLED。bundle各个生命周期状态的转换如下图所示:
启动级别:启动级别的数值越高,代表启动的阀值越高,即启动顺序越靠后。
- 只有System Bundle的启动级别可以为0,其他的均大于0(最大值为Integer.MAX_VALUE)。
- 动态启动级别:
- BundleActivator是Bundle的入口,与标准的Java应用程序中的静态main()函数类似
- BundleContext为应用提供执行是操作OSGi框架的方法
服务层
OSGi框架拥有一个集中的服务注册中心,它遵循发布-查询—绑定模型。
- 提供者Bundle可以将传统的java对象发布为服务
- 使用者Bundle可以找到并绑定服务
OSGi标准的服务属性
- ObjectClass、service.id(不可改变)
- service.pid、service.description、service.vendor
- service.ranking(值越大优先级越高)
- 服务注册对象是私有的,不能被别的Bundle共享,它们与发布服务的Bundle的生命周期是绑定的。
- 当Bundle停止时,任何没有移除服务都会被框架自动移除,Bundle停止时不必明确地注销服务。
- 先按照service.ranking从大到小排序,再按照service.id排序。
三种类型的事情:
- REGISTERED(注册):一个服务已经被注册并且可以立即使用。
- MODIFIED(更改):服务的一些元数据已经被修改。
- UNREGISTERED(注销):一个服务处于被注销的状态。
Bundle是动态的,服务随时可能消失,在调用服务前先判断服务是否为Null
- 当需要为不同的Bundle提供相同服务的不同实例需要使用ServiceFactory,同一个Bundle的多次请求会被OSGi框架缓存。
- 当服务使用Bundle的unGetService调用的次数等于GetService()及Bundle停止时清理缓存
- 服务钩子(Service Hook)
- EventListenerHook(当所有服务事件发生时)
- FindHook(当服务请求发生时)
- ListenerHook(当服务注册或者注销发生时时)
- 服务钩子可以实现一些AOP的功能。比如:增强服务,返回服务的代理