OSGI 学习笔记

OSGI最初是从嵌入式设备中发展起来的。后来由于Eclipse的成功,居于Equionx的RCP开发在桌面领域大方异彩。现在,互联网和基于浏览器的企业应用已成为整个IT业界最重要的组成部分,OSGI开始为服务器端应用和企业应用领域提供支持。OSGI 框架是一个微核结构的容器,所有的模块都需要运行在容器范围内,在 OSGI中所有模块的部署都必须以 Bundle的方式来进行部署。

目录

1. 前景

2. 名词解释

2.1 Bundle

2.2 Service

2.3 Service-Oriented Component Model

2.4 Declarative Service

2.5 Component

2.6 Service Hook

2.7 ServiceFactory

2.8 ServiceTracker

2.9 ServiceReference

3. 设计理念

3.1 模块化设计

3.2 面向服务的组件模型设计

3.3 动态性设计

3.4 可扩展的设计

3.5 面向接口的开发

4. OSGI R4

4.1 Core Framework

4.2 Module Layer

4.2.1 Bundle 的通讯机制

4.2.2  Bundle事件监听

4.3 LifeCycle Layer

4.4 Service Layer

4.4.1 Service事件监听

4.4.2 释放和注销服务

4.5 Security Layer

4.6 StartLevel Service

4.7 Declarative Services

4.8 Configuration Admin Service

4.9 Event Admin Service

4.10 ClassLoader

4.11 DS中Component 的生命周期

4.12 DS中Component 的通讯机制

5. OSGI R5

5.1 OSGi Bundle Repository(OBR)

5.2 Subsystems 服务规约

5.3 Resolver 服务规约

6. 流行框架

6.1 Equinox

6.2 Apache Felix

6.3 SpringDM

6.4 Knopflerfish

6.5 Oscar

6.6  alibaba hsf

7. equinox

7.1 Controlling the OSGi framework

7.2    Controlling Bundles

7.3    Displaying Status

7.4    Extras

7.5    Controlling the Profiling

7.6    Eclipse Runtime commands

7.7    Controlling the Console

8. 整合现有应用

8.1 web级

8.2 JPA

9. 构建可测试的OSGI

9.1 单元测试

9.2 集成测试

10. Q&A

10.1 Jdk9要支持osgi吗?

10.2 Servlet Container In OSGI和OSGI in Servlet Container?

10.3 ClassNotFoundException? NoClassDefError?

10.4 传统的mvc怎样分层

10.5 如何搭建分布式系统?Remote Services?

10.6 将传统的jar转为bundle风险?

10.7 如何保持Osgi动态性?

10.8 模块的实现和传统编程方法有何不同?


1. 前景

  • 可插拔的系统,部分的路由器都支持模块的热插拔,硬件界的这种热插拔技术一直就是软件界所追求的,而 OSGI则使得热插拔技术在软件界成为现实。
  • 可动态改变行为的系统,在业界可插拔的系统其实并不少,但可动态改变行为的系统并不多,,OSGI 有一整套完整的机制去实现动态改变系统行为。
  • 稳定、高效的系统,基于OSGI的系统采用的是微核机制,微核机制保证了系统的稳定性,微核机制的系统只要微核是稳定运行的,那么系统就不会崩溃。
  • 规范的、可积累的模块,为什么大部分软件公司都形成不了规范的模块开发方式呢?因为没有统一的规范的基础架构体系的定义,往往每个项目、每个产品都会因为架构师的偏好、技术的发展而导致模块的开发方式完全不同,这就使得软件公司在人员技能要求、培养上很难形成统一,而 OSGI 为这个问题提供了解决方案,基于 OSGI 的系统采用规范的模块开发、部署方式构建系统。当然,采用 OSGI 作为规范的模块开发、部署方式自然给现有梯队提出了新的要求,对于设计师而言,需要学习新的基于 OSGI 的模块分解、设计方式,对于开发人员而言,需要学习新的基于 OSGI 的开发方式,但对于公司形成规范的模块开发方式能带来的回报而言,这样的付出是值得的,而且,这个学习成本并不是很高。

2. 名词解释

2.1 Bundle

Bundle其实就是一个jar文件,这个jar文件和普通的jar文件唯一不同的地方就是Meta-inf目录下的MANIFEST.MF文件的内容,关于Bundle的所有信息都在MANIFEST.MF中进行描述,说的时髦点,可以称它为bundle的元数据,这些信息中包含有象Bundle的名称、描述、开发商、classpath、需要导入的包以及输出的包等等。

2.2 Service

一个OSGI Service就是注册到OSGI框架中的一个java对象。在注册时可以设置这个Service的属性。而在获取Service的时候可以根据属性进行过滤(Filter)。Bundle可以通过Bundle的上下文去注册Service或去查询Service。

OSGI 学习笔记_第1张图片

2.3 Service-Oriented Component Model

简称面向服务的组件模型,提出为了不通过代码的方式注册和获取服务的实例,而Delareative Service就能够使我们梦想成真。

2.4 Declarative Service

简称声明式服务或DS容器,对OSGI服务层提出的一直标准(可以看DI Container的影子)。OSGI的发展恰逢2005 SOA风潮最盛,目标是建立一个向后兼容的、内存可控的、可延迟服务激活的、使用配置来代替编码并消除平台侵入的新服务管理模型。

因此在OSGI R4 的重大改进,它对OSGI 的 Core Framework 进行了完善和提升,在 OSGI Core Framework对于系统采用的是 Module+Service的开发方式 ,但按照分结构的开发方式而言,系统按照的是 Module 分解为 Component+Service。

2.5 Component

定义(和Service 定义差不多

对外提供 Service;
使用其他 Component 提供的 Service; 
交由 OSGI 框架管理生命周期;

类型

Immediate:立即激活;
Delayed:延迟激活;
Factory:与Immediate基本相同只有在调用 ComponentFactory 的newInstance后才会激活里面的各个组件

引用策略(设置policy属性

Static: 默认的方式,在 Component 启动后,如果引用的 service 发生变动时,整个Component会重启;
Dynamic:而采用 dynamic 策略的情况下,在 Component 启动后,如果引用的 service 发生变动,并不会导致整个 Component 重启,而只会调用其中的 unbind和 bind 方法。
 

2.6 Service Hook

简称服务钩子,是开发人员干预Osgi框架和具体服务间交互过程的工具,R4.2版正式列入Osgi规范。本质上也是一个Osgi服务,提供了观察和空值服务注册表的相关操作,可以限定某个事件可以被那些Bundle接受到,也可以限定某个Bundle可以申请到哪些服务的应用。必须实现 org.osgi.framework.hooks.service.EventListenerHook 接口。

OSGI 学习笔记_第2张图片

2.7 ServiceFactory

无论多少个Bundle请求这个服务,获取的的服务对象实例都是同一个,也就是说这个服务是单例的,OSGI中默认的服务就是单例服务,服务对象中跟所有的方法都保持了无状态性。很多时候我们有这样的需求,服务的延迟创建(真正使用服务的时候再创建),无法满足。因此提出了服务工厂。通过implements ServiceFactory来完成。

注:服务工厂返回的多例是相对于多个Bundle调用而言的,即多个Bundle多个实例。在同一个Bundle中,Osgi容器对服务工厂的返回结果做了缓存,即使多次调用返回的仍然是同一个实例。

2.8 ServiceTracker

服务追踪器,如果系统使用了成百上千个服务,为了解决这些服务的相互依赖而去调配启动级别是一件非常可怕的工作,没有人愿意干这个事情。更何况,OSGI是天然的动态化执行环节,为了不让服务的使用者感到迷惑和复杂,需要一个能够持续追踪服务可用性的解决方案代替使用者去处理服务可用性的问题

需要导入org.osgi.util.tracker,创建一个类implements ServiceTrackerCustomizer,完成addingService、modifiedService、removedService方法的重写。

2.9 ServiceReference

引用服务,有的同学会注意到我们从BundleContext、ServiceReference和ServiceTracker中获取服务引用,将其存放至方法的局部变量中,在方法结束时随方法的栈帧一起销毁。为什么呢?另外Osgi设计的服务引用架构为什么每次使用服务都花费一次查询服务的开销?之所以这样设计,主要是考虑到自身动态执行环境,服务在Osgi环境中随时都可能被停用。

如果长期持有服务实例会有什么后果呢?当服务提供方的这个Bundle被停止后,服务引用依然是有效的,执行这个实例的接口不会报错的,当然这点也并不神秘,它只是一个普通的java对象,存在引用的java对象不可能自动销毁。更可怕的事情是,它的接口、实现类、实现类中引用的其他类以及加载这些类的类加载器都无法被垃圾回收器回收,当Bundle多次更新后,很可能形成内存泄露。

3. 设计理念

由于基于 OSGI 搭建系统带来的是架构级别的改变,带来的最大的影响莫过于设计层面,同时对于系统开发和部署也产生了影响。

3.1 模块化设计

尽管大家在设计大部分的系统时候确实是按照模块化的思想去进行的,但可能不会考虑的象 OSGI 定义 Bundle那么的清晰,但这点相信大家都能很快的适应,毕竟模块化的思想大致仍然是相同的,基于 OSGI 就可以按照统一的标准进行模块的设计,同时也会提升在模块设计时对于模块的输入(依赖)  、输出(功能) 、扩展的关注,从而使得模块的设计更加的完善和规范。

因为OSGi中的模块化是物理隔离的,而不基于OSGi的话很难做到物理隔离方式的模块化实现,也就很难使系统真正的做到模块化,通常切换到基于OSGi后就会发现以前的模块化设计做的还是很不足。 基于OSGi进行模块化的设计时和传统做设计时的模块设计并没有多大的差别,均为定义模块的范围、模块对外提供的服务和所依赖的服务。

3.2 面向服务的组件模型设计

面向服务的组件模型的设计思想是OSGi的核心设计思想,推崇系统采用Bundle的方式来划分,Bundle由多个Component来实现,Component 通过引用Service 或暴露 Service 来完成模块中用例的实现。应该说,这种基于OSGi实现的系统自然就是符合 SOA 体系架构的。

面向服务的组件模型设计更加强调在设计时分解模块中用例的实现(形成组件和服务)以及组件依赖的关注。 基于 OSGI 框架构建模块、Component、Service 的依赖时,体现出了超越传统 IoC 容器的优势,在依赖的构建上 OSGI 更是提供了多种灵活的依赖控制方式,例如属性过滤、版本过滤以及延迟加载设置等。

在OSGi中Component以POJO的方式编写,通过DI的方式注入其所引用的服务,以一个标准格式的 XML 描述 Component 引用服务的方式、对外提供的服务以及服务的属性。

3.3 动态性设计

要充分的发挥基于 OSGI 的动态性,就要完全的采用面向接口的设计方式,而不是去依赖实现,要记住基于 OSGI 搭建的系统是在运行期才构成依赖的,这和传统的系统有很大的差别,应该在运行期由 OSGI 框架自动的注入。 OSGI 提供的对于依赖的各种管理策略(如版本过滤、多样性设置等)在保证系统动态性的同时也保证了系统获取到所需的模块、Component或Service。

在设计时要记住的是所依赖的OSGi服务或Bundle都是有可能动态的卸载或安装的。为保持系统的动态性,在设计时要遵循的原则是不要静态化的依赖任何服务,避免服务不可用时造成系统的崩溃,另外保证系统的“即插即用,即删即无”。

3.4 可扩展的设计

OSGi在设计时提倡采用可扩展式的设计,即可通过系统中预设的扩展点来扩充系统的功能。有两种方式来实现:

  • 引用服务的方式

通过在组件中允许引用服务接口的多个实现来实现组件功能的不断扩展,例如A组件的作用为显示菜单,其通过引用菜单服务接口来获取系统中所有的菜单服务,此时系统中有两个实现此服务的组件,分别为文件菜单组件和编辑菜单组件,那么 A组件相应的就会显示出文件菜单和编辑菜单,而当从系统中删除编辑菜单的组件时,A组件显示的菜单就只剩文件菜单了,如此时再部署一个实现菜单服务接口的视图菜单组件模块到系统中,那么显示出来的菜单则会为文件、视图。

  • 定义扩展点的方式

按照 Eclipse 推荐的扩展点插件的标准格式定义 Bundle 中的扩展点,其他需要扩展的 Bundle 可通过实现相应的扩展点来扩展该 Bundle的功能。

3.5 面向接口的开发

OSGI 提供为每个 Bundle 提供独立的 ClassLoader 机制的方法则让我们可以真正的做到面向接口的开发。

4. OSGI R4

OSGI R4 规范由 Framework、Standard Services、Framework Services、System Services、Protocol Services、Miscellaneous Services 共同组成,在规范中对以上的各个方面进行了详细的介绍和规定,在这个章节中会深入的介绍 OSGI R4 中的关键部分,同时结合理论对之前的用户登录验证模块的实现进行讲解和改善。

4.1 Core Framework

OSGI 学习笔记_第3张图片

OSGI 学习笔记_第4张图片

L0运行环境是指标准的 JAVA环境。只要具备 Java 2 的构造和轮廓的都是被认可的运行环境。OSGI 同时也定义了一个可运行 Bundles 的最小环境的标准。

L1模块层定义了所采用的类加载(Classloader)机制。OSGI 是一个强大、严格、规范的类加载模型,基于 Java 但增加了模块化。在 Java 中,通常都是由一个 Classloader来加载所有的类和资源文件。在 OSGI 模块层中则为模块提供各自的 classloader,同时为模块的关联提供控制。

L2生命周期管理层则为 Bundles 的动态安装、启动、停止、更新和卸载提供了支持。基于 L1 提供的模块类加载机制的基础上,增加了一个对于 Bundle 的管理的 API。

L3增加了服务注册。服务注册为Bundles 提供了一个动态的协作模型。本来 Bundles可通过传统的 class 共享方式来实现协作,但在动态的安装和卸载代码的环境下这种方法是不适用的。服务注册为 Bundles 间共享Objects 提供了一种可用的模型,OSGI 提供了一堆的事件来通知服务的使用者关于服务的注册和卸载,服务其实就是简单的 Java objects。很多服务象 objects一样,例如 http server,而有些服务则代表了现实世界中的对象,例如蓝牙手机。

4.2 Module Layer

在OSGI规范中,将Module命名为Bundle,所以,在OSGI框架中是采用Bundle的方式来组织和部署系统的。包含:

  • Module的定义:定义MANIFEST.MF的元数据信息;
  • Module的package共享机制:包含Export-Package、Import-Package、Dynamic Imports(区别在于OSGI框架在resolve Bundle时就不会对其import的package做检测,到使用是才去获取);
  • Module的Classloader机制;
  • Module的国际化;
  • Module的校验;
  • 三种特殊形式的Bundle:包含Require Bundles、Fragment Bundles、Extension Bundles。

4.2.1 Bundle 的通讯机制

Bundle之间通过Service和Packages两种方式来进行通讯。Packages方式是通过定义Bundle的Import-Package和Export-Package来实现,Service机制可以实现引用其他 Bundle 中提供的类的实例。

OSGI 学习笔记_第5张图片

4.2.2  Bundle事件监听

Bundle事件

框架事件

BundleEvent类:

FrameworkEvent类

BundleListener接口

FrameworkListener接口

实现bundleChanged方法

实现frameworkEvent方法

BundleContext.addBundleListener()添加监听

BundleContext.addFrameworkListener()

添加监听

SynchronousBundleListener接口支持进行同步处理

 

都是默认异步执行的,不会阻塞Bundle和框架的状态转换

4.3 LifeCycle Layer

Lifecycle Layer基于Module Layer,使得基于OSGI框架可以动态的对Bundle的生命周期进行管理。 

包含Bundle的状态、管理Bundle的状态、监听Bundle的状态。

Bundle的状态

INSTALLED:Bundle已经成功的安装了。 
RESOLVED:Bundle中所需要的类都已解析好,可启动或者说 Bundle 已被停止。 
STARTING:Bundle正在启动中,BundleActivator的start方法已经被调用,但没返回。 
ACTIVE:Bundle已启动,并在运行中。 
STOPPING:Bundle正在停止中,BundleActivator的stop方法已经被调用,但没返回。 
UNINSTALLED:Bundle 已经被卸载。

监听Bundle的状态

在监听 Bundle 的状态上 OSGI 采用的是典型的 Java 中的事件机制,在 OSGI中事件分为 Framework Event和 Bundle Event 两种,Framework Event 用于报告 Framework 已启动、改变了 StartLevel、刷新了 packages或是出现了错误;而 Bundle Event 则用于报告 Bundle 的生命周期的改变。 可通过实现BundleListener或SynchronousBundleListener来监听Bundle Event,可通过实现 FrameworkListener来监听 Framework Event。

OSGI 学习笔记_第6张图片

4.4 Service Layer

Service Layer定义了Bundle 动态协作的服务发布、查找和绑定模型,Service Layer基于 Module Layer和 Lifecycle Layer,使得 OSGI 形成了完整的动态模型。包含:

  • 服务的注册;
  • 服务的获取;
  • 服务的监听

可以实现ServiceListener可监听Service的状态,推出Declarative Services之后,Service Layer其实就已经成为鸡肋了,Declarative Services提供了更好的服务注册、获取、监听等方式,使得其成为了OSGI R4 中的重要角色,并由此替代了Service Layer。

4.4.1 Service事件监听

SeviceEvent的枚举值

OSGI 学习笔记_第7张图片

服务层的所有事件分派都是同步的,OSGI规范定义了ServiceListener接口的ServiceChanged方法来实现监听服务编号时的执行逻辑。其实服务追踪器能感知添加和移除的编号,就是依赖这个完成的。ServiceTracker的内部类Tracked和AllTracked就是实现了ServiceListener接口,它的open()和close()方法分别调用了BundleContext.addServiceListener和BundleContext.removeServiceListener。

4.4.2 释放和注销服务

 释放服务是指服务使用者声明自己已经不再需要使用该服务对象的行为,服务提供者在OSGI框架注册了服务后,框架会使用引用计数的方式来跟踪服务对象实例是否被使用及被多少处使用。使用BundleContext.getService()申请服务时,计数器值+1,服务使用完后,通过BundleContext.ungetService(),计数器值-1。

注销服务的本质是把OSGI的服务从注册表中异常,当被移除后,与该服务相关的ServiceReference对象就失效了(不是绝对的,请看ServiceReference)。

注:一定要注意保存良好的习惯,否则会出现垃圾回收一直无法被回收的问题。

4.5 Security Layer

Security Layer在 OSGI 中采用的主要是 java 本身的 security策略和数字签名策略。

4.6 StartLevel Service

StartLevel Service 是 OSGI 规范中的核心服务,是 OSGI 框架必须实现的服务,通过 StartLevel Service 可以动态的设置和改变 Bundle 的启动顺序, OSGI 框架在启动Bundle 时按照启动顺序和 Bundle ID的倒序来启动系统。

  • 静态设置:config.ini设置 osgi.bundles.defaultStartLevel 的值来改变 Bundle 的默认启动级别
  • 动态设置:import org.osgi.service.startlevel

4.7 Declarative Services

见2.5 Component,更多

4.8 Configuration Admin Service

Configuration Admin Service 是 OSGI 中非常重要的一个服务,它用于动态的管理Bundle 的配置的属性,而这些属性的存储可能是在本地、也有可能是在远端、甚至可能会在某些设备上,基于 Configuration Admin Service 就可以统一的、动态的、远程的完成 Bundle 配置属性的管理工作了。

OSGI 学习笔记_第8张图片

4.9 Event Admin Service

OSGI提供了Event Admin Service以方便开发人员实现自定义的事件发布和事件处理,和 Java的事件处理模型基本是一致的。事件发布者通过调用 Event Admin Service 的 sendEvent 或postEvent 方法对外发布事件,事件订阅者则通过实现 Event Handler并注册为 EventHandler的服务来订阅感兴趣的事件。

4.10 ClassLoader

见3.5 面向接口的开发

4.11 DS中Component 的生命周期

尽管对于 Component 的控制 DS是提供了接口可以通过程序来实现控制的,但在实际的系统中基本都是交由 OSGI框架去控制,而很少通过程序主动去控制

4.12 DS中Component 的通讯机制

 DS中Component 的通讯通过服务的方式来完成,所以 DS 称自己为Component-Oriented Service Model。

5. OSGI R5

5.1 OSGi Bundle Repository(OBR)

Repository服务规约中提出的,就是OSGI的Bundle仓库,和maven类似都是组件参考,Apache Felix是OBR的一种实现,简化Bundle的部署和使用,另一方面也鼓励了独立Bundle的开发,OBR所以得功能都存在客户端,客户端只需要OBR的xml格式元文件就可以工作。这个文件定义了资源、依赖关系、源码位置、Bundle的位置信息。

5.2 Subsystems 服务规约

日益庞大的程序以及显得有些力不从心了,Osgi R5提出一个全新的、面向一组Bundle集合的管理系统和声明周期模型。

服务目标要解决的是资源隔离、资源共享、运行期动态变化等问题,站在战略层面上看为日OSGI in Clould做准备。

5.3 Resolver 服务规约

6. 流行框架

6.1 Equinox

Equinox是Eclipse旗下的OSGi框架,本身也被Eclipse采用,是Eclipse提供PDE开发环境的底层。Equinox本身也是相当的全面的框架,提供的功能丰富多样,它功能的分类就稍显混乱,文档和Sample也组织的不是很好。事实上相当Equinox还是被当做开发Eclipse Plugin的应用较多,如果你要开发一个Web程序,你就会感到它本身的功能和文档不够全面。Equinox最大的优势在于它和Eclipse结合紧密,只要你安装了PDE,你就已经有了Equinox,可以方便的在Eclipse里设置你开发的Bundle,启动、部署等操作也异常简单,而且有专门的Debug界面,你还能要求什么呢?

如果你想基于Eclipse开发,Equinox无疑是好选择。但对于新手而言,有时候会搞混Eclipse Plugin与OSGi的关系。

注:下载与eclipse的版本一致 http://download.eclipse.org/equinox/

6.2 Apache Felix

Apache Felix是Apache旗下的一个OSGi框架,项目本身非常成熟,已经被用到了很多其他的项目中,例如Apache Servicemix。它本身提供的服务也是最全的,几乎涵盖了全部的OSGi4.2的标准。除此之外还提供了一些非标准的功能,例如iPOJO。框架本身非常紧凑,你只需要3个包加一个shell就可以运行了,无论是开发还是Debug都非常简便。

除了Felix,还有两个项目是和OSGi相关的。一个是Apache Karaf,它本身是Felix的一个子项目,但他其实是封装了Felix提供更高一层的Runtime,例如提供了JAAS。另一个是Apache Aries,目前还处于起步阶段,它作为Felix的补充,提供OSGi企业级规范,包括JPA、JDBC、JTA、JNDI等等。

总的来说,Apache Felix是我个人推荐的最佳OSGi框架,它简单的结构也更适合出学OSGi的开发人员。

传统方式:http://www.cnblogs.com/skyme/archive/2012/07/11/2584936.html

考虑使用下面:

BndTools为在Eclipse中提供支持

http://bndtools.org/tutorial.html

http://www.infoq.com/cn/news/2011/12/bndtools-11

在这个命令行下输入help我们就可以看到大部分的指令,为了避免命令名字的冲突,这些命令都有自己的名字空间,现有的名字空间有三种:

1. felix:关于felix框架的核心命令,比如列出所有bundle,安装/卸载bundle等等

2.gogo - 包含grep,cat,echo这类的指令,并且gogo是个Felix的子项目,他是参照RFC147来实现的,这个标准定义了OSGi环境的shell应该是怎么样的。

3.obr - 关于OSGi Bundle Repository功能的指令

如果对任何的命令有所疑问,用help+空格+“命令名称”来查看说明即可。

6.3 SpringDM

Spring DM是Spring旗下的OSGi框架,Spring我想大家都知道了,Spring DM的最大特点就是结合了Spring框架。我之所以说特点还不是优势,是因为我认为这个需求本身就是错误的。Spring核心就是一个IoC,当然后来它的外延扩大了,提供了越来越多乱七八糟的功能。OSGi规范本身就制定了一系列IoC的功能标准,尤其是其中的BluePrint其实相当多的借鉴了Spring,因此完全没有必要再引入Spring充当新的IoC了。Spring本身无论是ClassLoader还是配置文件上都与OSGi格格不入,之所以有这种需求是因为现在有大量基于Spring的项目想要过渡到OSGi上。Spring还发布了一个App Server叫Spring DM Server,是一个基于Spring DM的App Server,你会发现你需要加载80+的包来完成一个hello world操作,这种恐怖的依赖性正是Spring所带来的。

传闻Spring DM和Spring DM Server都将会移交给Eclipse。就目前来说除非你有基于Spring项目的移植需求,我不推荐其他任何情况下使用Spring DM。

6.4 Knopflerfish

Knopflerfish是一个知名的OSGI框架,OSGi的先行者,它本身是一个相当标准OSGi框架,提供了绝大多数标准功能,目前提供的最新版本也已经完整的实现了OSGI R4,Knopflerfish 的开发状态非常的活跃,同时它也提供了为方便开发基于 OSGI 系统的大量的 Bundle。 但是无论在人气上,开发进度上,文档完善上都不如其他的三者。

6.5 Oscar

Oscar是一个遵循 OSGI R3 框架的实现,目前它的开发状态不怎么的活跃,最新的新闻都是 2005年的了。

Oscar的优势在于提供了大量 OSGI R3 标准之外的 Bundle,为开发基于 OSGI 的系统提供了方便。

6.6  alibaba hsf

阿里巴巴集团内部使用的分布式服务框架 HSF(High Speed Framework,也有人戏称“好舒服”)已经被很多技术爱好者所熟知,目前已经支撑着近 2000 多个应用的运行,但目前无开源。

7. equinox

7.1 Controlling the OSGi framework

launch

start the OSGi Framework

shutdown

shutdown the OSGi Framework

close

shutdown and exit

exit

exit immediately (System.exit)

init

uninstall all bundles

setprop =

set the OSGi property

7.2    Controlling Bundles

install

安装对应id的Bundle

如:install file:./dictQuery_1.0.0.201610281721.jar

uninstall

卸载对应id的Bundle

start

启动对应id的Bundle

stop

停止对应id的Bundle

update

更新对应id的Bundle

refresh

刷新对应id的Bundle

7.3    Displaying Status

ss

display installed bundles

status

display installed bundles and registered services

services [filter]

显示所有已services详情. Examples for [filter]: (objectClass=com.xyz.Person); (&(objectClass=com.xyz.Person)(|(sn=Jensen)(cn=Babs J*))); passing only com.xyz.Person is a shortcut for (objectClass=com.xyz.Person). The filter syntax specification is available at

packages [||]

display imported/exported package details

bundles

display details for all installed bundles

bundle

display details for the specified bundle(s)

headers

print bundle headers

7.4    Extras

exec

execute a command in a separate process and wait

fork

execute a command in a separate process

gc

perform a garbage collection

getprop

displays the system properties with the given name, or all of them.

props

Display system properties

threads

Display threads and thread groups

7.5    Controlling the Profiling

profilelog

Display & flush the profile log messages

7.6    Eclipse Runtime commands

diag

Displays unsatisfied constraints for the specified bundle(s).

enableBundle

enable the specified bundle(s)

disableBundle

disable the specified bundle(s)

disabledBundles

list disabled bundles in the system

7.7    Controlling the Console

more

More prompt for console output

disconnect

Disconnects from telnet session

help

Display help for the specified command

8. 整合现有应用

8.1 web级

Servlet

已基本上支持

struts/struts2

基本支持

springmvc

只能结合SpringDM来整合

8.2 JPA

Eclipselink

支持性很好,官方推荐使用

openJpa

没尝试,据说还有些包会有问题,http://openjpa.apache.org/

hibernate 官网给出支持
mybatis

支持性不够

9. 构建可测试的OSGI

9.1 单元测试

OSGI 学习笔记_第9张图片

缺点:发布时要除去测试代码,整个工程项目都必须导入Junit、Jmockit等测试工具库的Bundle。

OSGI 学习笔记_第10张图片

缺点:属于不同的类加载器,只能测试导出的类(不是所有的类都能被测试到)

解决:

  1. 修改程序Bundle的外部接口描述,将需要测试的类全部到场,添加“x-friends”标记限定资源测试Bundle能访问这些接口,这个方案需要用到Equinox的私有标记,而且污染到程序Bundle元数据。
  2. 使用测试Bundle的类路径(ClassPath),将源码Bundle添加到测试Bundel的类路径之中,时间上没有把源码Bundle当做Osgi看到,只是一个普通的JAR包

OSGI 学习笔记_第11张图片

不仅将测试代码和程序代码分开,也能保证运行时两者在同一个类加载器中,可以无限制访问源码Bundel中任何资源。

也就是Fragment Bundle模式

9.2 集成测试

需要自动启动Osgi环境,完成对export的service进行测试,目前测试框架:

Eclipse junit plug-in test

Spring dm test

Pax exam

OSGI 学习笔记_第12张图片

10. Q&A

10.1 Jdk9要支持osgi吗?

要支持的,但是非osgi,比目前的Osig要low,具体参阅

10.2 Servlet Container In OSGI和OSGI in Servlet Container?

OSGI 学习笔记_第13张图片

Equinox框架对两种都提供了比较完善的支持。

前者多用于生产环境之中,这样web服务器不受限制,可以选择tomcat、weblogic、websphere,能获得可靠的容器支持;

后者多用于开发调试中,一般选用嵌入式Jetty等相对轻量的服务器,实现高速的服务启动、更新和调试

10.3 ClassNotFoundException? NoClassDefError?

了解classloader之后,这两个也是在 ClassLoader 加载类出现问题时常常碰到的两个异常,这两个异常的区别在于前者ClassNotFoundException 是指通过 ClassLoader 加载不到所需要的类,而后者NoClassDefError是指通过 ClassLoader已经找到了所需要的类,但找不到该类所依赖的其他的类。

10.4 传统的mvc怎样分层

满足OSGI的设计理念基础上,模块划分的粒度没有明确的指导法则,需要根据设计师们的经验来确定,最基本的原则是职责单一的原则。

例如:留言板系统本身的功能较为简单,在模块的划分上就按照功能职责来划分,每个模块中直接包含了页面层+持久层的实现,不再划分为页面层的 Bundle 和持久层的 Bundle,按照留言板的功能需求将系统的模块划分。

OSGI 学习笔记_第14张图片

OSGI 学习笔记_第15张图片

10.5 如何搭建分布式系统?Remote Services?

OSGI 学习笔记_第16张图片

针对跨进程的OSGI应用,Remote Services为期用提供了规范。

目前支持的分布式技术:

  • Apache CXF:基于SOAP协议,较为传统
  • Equinox ECF:https://wiki.eclipse.org/OSGi_Remote_Services_and_ECF
  • Apache Axis:基于RPC协议,参阅http://osgi.com.cn/article/7289431

另外:是否有必要这样做?

个人认为,如果构建SOA级的应用,就需要部署到ESB中,真的需要这么细粒度的服务?

10.6 将传统的jar转为bundle风险?

为何要这样做?其实osgi本身提供了动态导入本地的非bundle,但我希望你能想清楚这样做的后果。其实现在也有解决方案,可使用Eclipse的PDE中可视化界面来将jar转为bundle。

10.7 如何保持Osgi动态性?

遵循osg设计理念及相关规约

10.8 模块的实现和传统编程方法有何不同?

林昊:模块的实现和传统的编程方法确实有一些差别,主要体现在模块之间类访问的隔离、版本选择这两个方面。如希望更好的设计模块化的系统,开发者需要学习ClassLoader机制、模块之间类的交互方法(这包括了模块怎么样对外提供可访问的package、怎么样访问其他模块提供的package、如何选择适合版本的package等)

你可能感兴趣的:(#,组件)