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 模块的实现和传统编程方法有何不同?
Bundle其实就是一个jar文件,这个jar文件和普通的jar文件唯一不同的地方就是Meta-inf目录下的MANIFEST.MF文件的内容,关于Bundle的所有信息都在MANIFEST.MF中进行描述,说的时髦点,可以称它为bundle的元数据,这些信息中包含有象Bundle的名称、描述、开发商、classpath、需要导入的包以及输出的包等等。
一个OSGI Service就是注册到OSGI框架中的一个java对象。在注册时可以设置这个Service的属性。而在获取Service的时候可以根据属性进行过滤(Filter)。Bundle可以通过Bundle的上下文去注册Service或去查询Service。
简称面向服务的组件模型,提出为了不通过代码的方式注册和获取服务的实例,而Delareative Service就能够使我们梦想成真。
简称声明式服务或DS容器,对OSGI服务层提出的一直标准(可以看DI Container的影子)。OSGI的发展恰逢2005 SOA风潮最盛,目标是建立一个向后兼容的、内存可控的、可延迟服务激活的、使用配置来代替编码并消除平台侵入的新服务管理模型。
因此在OSGI R4 的重大改进,它对OSGI 的 Core Framework 进行了完善和提升,在 OSGI Core Framework对于系统采用的是 Module+Service的开发方式 ,但按照分结构的开发方式而言,系统按照的是 Module 分解为 Component+Service。
定义(和Service 定义差不多)
对外提供 Service;
使用其他 Component 提供的 Service;
交由 OSGI 框架管理生命周期;
类型
Immediate:立即激活;
Delayed:延迟激活;
Factory:与Immediate基本相同只有在调用 ComponentFactory 的newInstance后才会激活里面的各个组件
引用策略(设置policy属性)
Static: 默认的方式,在 Component 启动后,如果引用的 service 发生变动时,整个Component会重启;
Dynamic:而采用 dynamic 策略的情况下,在 Component 启动后,如果引用的 service 发生变动,并不会导致整个 Component 重启,而只会调用其中的 unbind和 bind 方法。
简称服务钩子,是开发人员干预Osgi框架和具体服务间交互过程的工具,R4.2版正式列入Osgi规范。本质上也是一个Osgi服务,提供了观察和空值服务注册表的相关操作,可以限定某个事件可以被那些Bundle接受到,也可以限定某个Bundle可以申请到哪些服务的应用。必须实现 org.osgi.framework.hooks.service.EventListenerHook 接口。
无论多少个Bundle请求这个服务,获取的的服务对象实例都是同一个,也就是说这个服务是单例的,OSGI中默认的服务就是单例服务,服务对象中跟所有的方法都保持了无状态性。很多时候我们有这样的需求,服务的延迟创建(真正使用服务的时候再创建),无法满足。因此提出了服务工厂。通过implements ServiceFactory
注:服务工厂返回的“多例”是相对于多个Bundle调用而言的,即多个Bundle多个实例。在同一个Bundle中,Osgi容器对服务工厂的返回结果做了缓存,即使多次调用返回的仍然是同一个实例。
服务追踪器,如果系统使用了成百上千个服务,为了解决这些服务的相互依赖而去调配启动级别是一件非常可怕的工作,没有人愿意干这个事情。更何况,OSGI是天然的动态化执行环节,为了不让服务的使用者感到迷惑和复杂,需要一个能够持续追踪服务可用性的解决方案代替使用者去处理服务可用性的问题。
需要导入org.osgi.util.tracker,创建一个类implements ServiceTrackerCustomizer,完成addingService、modifiedService、removedService方法的重写。
引用服务,有的同学会注意到我们从BundleContext、ServiceReference和ServiceTracker中获取服务引用,将其存放至方法的局部变量中,在方法结束时随方法的栈帧一起销毁。为什么呢?另外Osgi设计的服务引用架构为什么每次使用服务都花费一次查询服务的开销?之所以这样设计,主要是考虑到自身动态执行环境,服务在Osgi环境中随时都可能被停用。
如果长期持有服务实例会有什么后果呢?当服务提供方的这个Bundle被停止后,服务引用依然是有效的,执行这个实例的接口不会报错的,当然这点也并不神秘,它只是一个普通的java对象,存在引用的java对象不可能自动销毁。更可怕的事情是,它的接口、实现类、实现类中引用的其他类以及加载这些类的类加载器都无法被垃圾回收器回收,当Bundle多次更新后,很可能形成内存泄露。
由于基于 OSGI 搭建系统带来的是架构级别的改变,带来的最大的影响莫过于设计层面,同时对于系统开发和部署也产生了影响。
尽管大家在设计大部分的系统时候确实是按照模块化的思想去进行的,但可能不会考虑的象 OSGI 定义 Bundle那么的清晰,但这点相信大家都能很快的适应,毕竟模块化的思想大致仍然是相同的,基于 OSGI 就可以按照统一的标准进行模块的设计,同时也会提升在模块设计时对于模块的输入(依赖) 、输出(功能) 、扩展的关注,从而使得模块的设计更加的完善和规范。
因为OSGi中的模块化是物理隔离的,而不基于OSGi的话很难做到物理隔离方式的模块化实现,也就很难使系统真正的做到模块化,通常切换到基于OSGi后就会发现以前的模块化设计做的还是很不足。 基于OSGi进行模块化的设计时和传统做设计时的模块设计并没有多大的差别,均为定义模块的范围、模块对外提供的服务和所依赖的服务。
面向服务的组件模型的设计思想是OSGi的核心设计思想,推崇系统采用Bundle的方式来划分,Bundle由多个Component来实现,Component 通过引用Service 或暴露 Service 来完成模块中用例的实现。应该说,这种基于OSGi实现的系统自然就是符合 SOA 体系架构的。
面向服务的组件模型设计更加强调在设计时分解模块中用例的实现(形成组件和服务)以及组件依赖的关注。 基于 OSGI 框架构建模块、Component、Service 的依赖时,体现出了超越传统 IoC 容器的优势,在依赖的构建上 OSGI 更是提供了多种灵活的依赖控制方式,例如属性过滤、版本过滤以及延迟加载设置等。
在OSGi中Component以POJO的方式编写,通过DI的方式注入其所引用的服务,以一个标准格式的 XML 描述 Component 引用服务的方式、对外提供的服务以及服务的属性。
要充分的发挥基于 OSGI 的动态性,就要完全的采用面向接口的设计方式,而不是去依赖实现,要记住基于 OSGI 搭建的系统是在运行期才构成依赖的,这和传统的系统有很大的差别,应该在运行期由 OSGI 框架自动的注入。 OSGI 提供的对于依赖的各种管理策略(如版本过滤、多样性设置等)在保证系统动态性的同时也保证了系统获取到所需的模块、Component或Service。
在设计时要记住的是所依赖的OSGi服务或Bundle都是有可能动态的卸载或安装的。为保持系统的动态性,在设计时要遵循的原则是不要静态化的依赖任何服务,避免服务不可用时造成系统的崩溃,另外保证系统的“即插即用,即删即无”。
OSGi在设计时提倡采用可扩展式的设计,即可通过系统中预设的扩展点来扩充系统的功能。有两种方式来实现:
通过在组件中允许引用服务接口的多个实现来实现组件功能的不断扩展,例如A组件的作用为显示菜单,其通过引用菜单服务接口来获取系统中所有的菜单服务,此时系统中有两个实现此服务的组件,分别为文件菜单组件和编辑菜单组件,那么 A组件相应的就会显示出文件菜单和编辑菜单,而当从系统中删除编辑菜单的组件时,A组件显示的菜单就只剩文件菜单了,如此时再部署一个实现菜单服务接口的视图菜单组件模块到系统中,那么显示出来的菜单则会为文件、视图。
按照 Eclipse 推荐的扩展点插件的标准格式定义 Bundle 中的扩展点,其他需要扩展的 Bundle 可通过实现相应的扩展点来扩展该 Bundle的功能。
OSGI 提供为每个 Bundle 提供独立的 ClassLoader 机制的方法则让我们可以真正的做到面向接口的开发。
OSGI R4 规范由 Framework、Standard Services、Framework Services、System Services、Protocol Services、Miscellaneous Services 共同组成,在规范中对以上的各个方面进行了详细的介绍和规定,在这个章节中会深入的介绍 OSGI R4 中的关键部分,同时结合理论对之前的用户登录验证模块的实现进行讲解和改善。
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,而有些服务则代表了现实世界中的对象,例如蓝牙手机。 |
在OSGI规范中,将Module命名为Bundle,所以,在OSGI框架中是采用Bundle的方式来组织和部署系统的。包含:
Bundle之间通过Service和Packages两种方式来进行通讯。Packages方式是通过定义Bundle的Import-Package和Export-Package来实现,Service机制可以实现引用其他 Bundle 中提供的类的实例。
Bundle事件 |
框架事件 |
BundleEvent类: |
FrameworkEvent类 |
BundleListener接口 |
FrameworkListener接口 |
实现bundleChanged方法 |
实现frameworkEvent方法 |
BundleContext.addBundleListener()添加监听 |
BundleContext.addFrameworkListener() 添加监听 |
SynchronousBundleListener接口支持进行同步处理 |
|
都是默认异步执行的,不会阻塞Bundle和框架的状态转换 |
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。
Service Layer定义了Bundle 动态协作的服务发布、查找和绑定模型,Service Layer基于 Module Layer和 Lifecycle Layer,使得 OSGI 形成了完整的动态模型。包含:
可以实现ServiceListener可监听Service的状态,推出Declarative Services之后,Service Layer其实就已经成为鸡肋了,Declarative Services提供了更好的服务注册、获取、监听等方式,使得其成为了OSGI R4 中的重要角色,并由此替代了Service Layer。
SeviceEvent的枚举值
服务层的所有事件分派都是同步的,OSGI规范定义了ServiceListener接口的ServiceChanged方法来实现监听服务编号时的执行逻辑。其实服务追踪器能感知添加和移除的编号,就是依赖这个完成的。ServiceTracker的内部类Tracked和AllTracked就是实现了ServiceListener接口,它的open()和close()方法分别调用了BundleContext.addServiceListener和BundleContext.removeServiceListener。
释放服务是指服务使用者声明自己已经不再需要使用该服务对象的行为,服务提供者在OSGI框架注册了服务后,框架会使用引用计数的方式来跟踪服务对象实例是否被使用及被多少处使用。使用BundleContext.getService()申请服务时,计数器值+1,服务使用完后,通过BundleContext.ungetService(),计数器值-1。
注销服务的本质是把OSGI的服务从注册表中异常,当被移除后,与该服务相关的ServiceReference对象就失效了(不是绝对的,请看ServiceReference)。
注:一定要注意保存良好的习惯,否则会出现垃圾回收一直无法被回收的问题。
Security Layer在 OSGI 中采用的主要是 java 本身的 security策略和数字签名策略。
StartLevel Service 是 OSGI 规范中的核心服务,是 OSGI 框架必须实现的服务,通过 StartLevel Service 可以动态的设置和改变 Bundle 的启动顺序, OSGI 框架在启动Bundle 时按照启动顺序和 Bundle ID的倒序来启动系统。
见2.5 Component,更多
Configuration Admin Service 是 OSGI 中非常重要的一个服务,它用于动态的管理Bundle 的配置的属性,而这些属性的存储可能是在本地、也有可能是在远端、甚至可能会在某些设备上,基于 Configuration Admin Service 就可以统一的、动态的、远程的完成 Bundle 配置属性的管理工作了。
OSGI提供了Event Admin Service以方便开发人员实现自定义的事件发布和事件处理,和 Java的事件处理模型基本是一致的。事件发布者通过调用 Event Admin Service 的 sendEvent 或postEvent 方法对外发布事件,事件订阅者则通过实现 Event Handler并注册为 EventHandler的服务来订阅感兴趣的事件。
见3.5 面向接口的开发
尽管对于 Component 的控制 DS是提供了接口可以通过程序来实现控制的,但在实际的系统中基本都是交由 OSGI框架去控制,而很少通过程序主动去控制
DS中Component 的通讯通过服务的方式来完成,所以 DS 称自己为Component-Oriented Service Model。
Repository服务规约中提出的,就是OSGI的Bundle仓库,和maven类似都是组件参考,Apache Felix是OBR的一种实现,简化Bundle的部署和使用,另一方面也鼓励了独立Bundle的开发,OBR所以得功能都存在客户端,客户端只需要OBR的xml格式元文件就可以工作。这个文件定义了资源、依赖关系、源码位置、Bundle的位置信息。
日益庞大的程序以及显得有些力不从心了,Osgi R5提出一个全新的、面向一组Bundle集合的管理系统和声明周期模型。
服务目标要解决的是资源隔离、资源共享、运行期动态变化等问题,站在战略层面上看为日OSGI in Clould做准备。
略
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/
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+空格+“命令名称”来查看说明即可。
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。
Knopflerfish是一个知名的OSGI框架,OSGi的先行者,它本身是一个相当标准OSGi框架,提供了绝大多数标准功能,目前提供的最新版本也已经完整的实现了OSGI R4,Knopflerfish 的开发状态非常的活跃,同时它也提供了为方便开发基于 OSGI 系统的大量的 Bundle。 但是无论在人气上,开发进度上,文档完善上都不如其他的三者。
Oscar是一个遵循 OSGI R3 框架的实现,目前它的开发状态不怎么的活跃,最新的新闻都是 2005年的了。
Oscar的优势在于提供了大量 OSGI R3 标准之外的 Bundle,为开发基于 OSGI 的系统提供了方便。
阿里巴巴集团内部使用的分布式服务框架 HSF(High Speed Framework,也有人戏称“好舒服”)已经被很多技术爱好者所熟知,目前已经支撑着近 2000 多个应用的运行,但目前无开源。
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 |
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 |
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 |
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 |
profilelog |
Display & flush the profile log messages |
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 |
more |
More prompt for console output |
disconnect |
Disconnects from telnet session |
help |
Display help for the specified command |
Servlet | 已基本上支持 |
struts/struts2 | 基本支持 |
springmvc | 只能结合SpringDM来整合 |
Eclipselink | 支持性很好,官方推荐使用 |
openJpa | 没尝试,据说还有些包会有问题,http://openjpa.apache.org/ |
hibernate | 官网给出支持 |
mybatis | 支持性不够 |
缺点:发布时要除去测试代码,整个工程项目都必须导入Junit、Jmockit等测试工具库的Bundle。
缺点:属于不同的类加载器,只能测试导出的类(不是所有的类都能被测试到)
解决:
不仅将测试代码和程序代码分开,也能保证运行时两者在同一个类加载器中,可以无限制访问源码Bundel中任何资源。
也就是Fragment Bundle模式
需要自动启动Osgi环境,完成对export的service进行测试,目前测试框架:
Eclipse junit plug-in test
Spring dm test
Pax exam
要支持的,但是非osgi,比目前的Osig要low,具体参阅
Equinox框架对两种都提供了比较完善的支持。
前者多用于生产环境之中,这样web服务器不受限制,可以选择tomcat、weblogic、websphere,能获得可靠的容器支持;
后者多用于开发调试中,一般选用嵌入式Jetty等相对轻量的服务器,实现高速的服务启动、更新和调试
了解classloader之后,这两个也是在 ClassLoader 加载类出现问题时常常碰到的两个异常,这两个异常的区别在于前者ClassNotFoundException 是指通过 ClassLoader 加载不到所需要的类,而后者NoClassDefError是指通过 ClassLoader已经找到了所需要的类,但找不到该类所依赖的其他的类。
满足OSGI的设计理念基础上,模块划分的粒度没有明确的指导法则,需要根据设计师们的经验来确定,最基本的原则是职责单一的原则。
例如:留言板系统本身的功能较为简单,在模块的划分上就按照功能职责来划分,每个模块中直接包含了页面层+持久层的实现,不再划分为页面层的 Bundle 和持久层的 Bundle,按照留言板的功能需求将系统的模块划分。
针对跨进程的OSGI应用,Remote Services为期用提供了规范。
目前支持的分布式技术:
另外:是否有必要这样做?
个人认为,如果构建SOA级的应用,就需要部署到ESB中,真的需要这么细粒度的服务?
为何要这样做?其实osgi本身提供了动态导入本地的非bundle,但我希望你能想清楚这样做的后果。其实现在也有解决方案,可使用Eclipse的PDE中可视化界面来将jar转为bundle。
遵循osg设计理念及相关规约
林昊:模块的实现和传统的编程方法确实有一些差别,主要体现在模块之间类访问的隔离、版本选择这两个方面。如希望更好的设计模块化的系统,开发者需要学习ClassLoader机制、模块之间类的交互方法(这包括了模块怎么样对外提供可访问的package、怎么样访问其他模块提供的package、如何选择适合版本的package等)