众所周知。对于高动态高可扩展的应用,OSGI是一个很好的平台。可是。也因此添加了复杂性。开发中对service的依赖变得复杂。
这也是service的关系管理成为OSGI中一个很重要的部分,我们来看看OSGI中service依赖关系管理的方式。
篇幅原因,仅仅关注发展历程,不具体介绍每一个方式的具体实现细节。
概括的说。眼下在OSGI中主要有下面几种service依赖关系管理的方法:
1. Service listener
2. Service binder
3. Dependency Manager
4. Declarative Services
5. iPOJO
6. blueprint
1) Service Listener
这是OSGI中原生的service依赖管理机制,是最简单直接的方式,其基本原理很easy,标准的注冊/查找:
1. 被依赖的bundle通过BundleContext.registerService()方法注冊服务到系统中
2. 使用依赖的bundle在start时通过BundleContext的getServiceReferences()/getService()来查找依赖的service
3. 使用依赖bundle通过BundleContext.addServiceListener()来分别注冊ServiceListener
4. 在被依赖的bundle/service状态发生变化时, 使用依赖bundle通过ServiceListener的serviceChanged()得到通知并作出调整。
在这样的方法中,使用依赖的Service必须进行大量的编码工作来完毕对依赖的service的关系管理,须要处理琐碎细节如各个Service的执行时状态变化。为了降低工作量,OSGI设计了ServiceTracker来简化对依赖service的编码工作。即ServiceTracker将负责处理上述步骤中的2/3/4。
经过ServiceTracker优化后的Service Listener机制。还是存在一些缺点:
1. 编码量还是不小,尤其对于依赖较多的场景
2. Activator 还是太复杂了,虽然已经非常努力的试图简化
对于一些业务逻辑简单的service,假设依赖的service比較多,那么Activator的逻辑和代码实现远比service本身的逻辑和实现要复杂。这违背了我们使用框架简化开发的初衷。
3. Activator对測试不利
这个是Activator的复杂性造成的,因为Activator中存在大量的依赖处理逻辑,理所当然的会添加測试的复杂性。
总结说。Service Listener 机制下。管理service依赖对于开发人员来说全然是个重体力活: 非常重要。常常要做,easy出现错误, 出错时不easy測试。并且,这些工作都不是service 业务逻辑的组成部分。不能带来直接收益。简言之,吃力不讨好,一不小心就搬石头砸自己的脚。
更重要的。从分工的角度上将。开发者应该将很多其它的精力投入与应用的逻辑,而不是OSGI的底层实现机制。因此,从2000之后,就陆续有人開始考虑对此改进。
2) Service binder
Service binder OSGI针对这个问题的一个尝试,基本出发点很明白:希望找到一个通用的方法来简化OSGI下的动态service依赖管理.
最初開始这个工作的是两位大牛。Richard S. Hall和Humberto,大概在2002年的时候开发完毕。
看我们看Service binder是怎么做的。基本步骤为:
1. 提供一个org.apache.felix.servicebinder.GenericActivator;
如今bundle的Activator仅仅要简单的继承GenericActivator就能够了,全部的代码实如今GenericActivator提供,降低代码的目标顺利达成。这个能够说足够简单到没有办法再简单了。
2. 通过metadata.xml 来实现service的依赖注入
3. 详细的service的实现类基本就是一个干净的POJO了
当然还是须要实现bind-method/unbind-method 两个方法。好在这个是通过metadata.xml来做映射,不是另外提供接口定义,因此勉强避开了"侵入"的问题。
Service binder 机制在降低Activator方面成效显著,可是引入的metadata.xml文件似乎又带来了新的问题。xml配置文件的可维护性个人感觉值得怀疑。用过EJB的同学都明确。EJB的部署文件有多令人烦恼。
当然Service binder 的思路很的正确:通过引入了自己主动化的service依赖关系管理。简化开发,同意开发者能够集中精力在service的实现上,而不是疲于处理依赖关系管理。
Service binder的实现似乎并没有被推广开。由于非常快OSGI就在2004年的OSGI R4规范中引入了Declarative Services。因此Felix也就终止了对Service binder的兴许支持。
3) Dependency Manager
继Service binder之后,Felix又提供了名为Dependency Manager 的service依赖管理方式。对照Service binder,个人感觉这个Dependency Manager 仅仅是针对Service binder的一个改进:将metadata.xml 文件取消,由新引入的DependencyManager来实现metadata.xml 文件的功能。原来在metadata.xml 文件里的配置转变为在Activator中通过代码调用DependencyManager来实现.
Dependency Manager事实上现的方式为:
1. 提供org.apache.felix.dependencymanager.DependencyActivatorBase
bundle的Activator须要继承DependencyActivatorBase,并实现DependencyActivatorBase要求的init()/destroy()方法
2. 在init()中,能够通过DependencyManager 对象来注冊服务,并注明依赖。
3. 详细的Service类能够是POJO。DependencyManager 通过反射来注入依赖的service。
Felix 官方给出了一个Dependency Manager的使用演示样例
http://felix.apache.org/site/dependency-manager-usage.html
从演示样例上看,对service的依赖管理已经简化了很多。
这里另一个05年的介绍Dependency Manager的 presentation:
http://felix.apache.org/site/presentations.data/DependencyManagement.pdf
4) Declarative Services
2004年公布的OSGi的4.0版本号中,增加了Declarative Services。据说是从Service Binder进化而来。
Declarative Services的实现方式和Service Binder的确很相似:
1. 相同是须要一个xml文件来配置
在 bundle manifest中添加Service-Component 的header
提供的功能和Service Binder非常类似。配置方法也非常接近。
2. 相同的提供bind/unbind 方法的配置
对于每一个依赖的service,都能够在配置文件里通过指定bind/unbind 方法来处理依赖的状态变化。
此外,Declarative Services 提供两个特殊的lifecircle方法:
protected void activate(ComponentContext context)
protected void deactivate(ComponentContext context)
假设service实现类提供了这两个方法,则Declarative Services 会自己主动识别并调用这两个方法。注意这两个方法没有接口定义进行强约束。仅仅是一个约定而已。预计是为了避免OSGI对service的侵入。
Declarative Services 是OSGI规范的一部分,因此Declarative Services的支持自然是各个OSGI实现都提供的。
从功能上将,Declarative Services 基本已经不错了,可是大牛们的脚步并未就此停住。
5) iPOJO
2005年,Richard 開始考虑使用字节码生成技术来进行创建组合服务的改进。另外一个牛人Peter Kriens也相同的工作并实现了一个原型。
2006年,Clement Escoffier 和 Richard 開始开发iPOJO。合并了Peter Kriens之前的工作内容,这就是iPOJO的由来。
对于iPOJO的定义。Felix的iPOJO页面有例如以下说明:iPOJO是一个server组件执行时,目标在于简化OSGI应用开发。原生支持全部的OSGI活力。给予POJO的概念,应用逻辑开发简单。
非功能性的属性在执行时被注入到组件中。
相同看看Felix对iPOJO长处的说明:
1. 组件被作为POJO开发,不须要其它不论什么东西
2. 组件模块是可扩展的,因此能够自由的适应须要
3. 标准组件模型管理service 供应和service 依赖,所以能够要求其它不论什么OSGI服务来创建组合服务,
4. iPOJO管理组件实例的生命周期和环境动态
5. iPOJO提供一个强力的组合系统来创建高度动态的应用
6. iPOJO支持注解,xml或者基于Java的API来定义组件
能够看到iPOJO的功能远比之前的几个解决方式要强大,除了支持Declarative Services已经实现的功能外,还提供了强大的注解支持。并且实现了组合系统。这些对于开发大型的复杂应用时很实用的。
Richard 在他的presentation谈到iPOJO 的设计思路:
1. Make things simple / 让事情简单
2. Follow POJO philosophy / 遵循POJO的哲学
3. Employ byte code manipulation techniques / 使用字节码操纵技术
4. Be as lazy as possible / 尽可能的偷懒
眼下的iPOJO还在继续发展中。最新的一个版本号iPOJO 1.6.0在2010-04-25公布。
6) blueprint
blueprint 是OSGI为了解决上述问题的最新尝试。在去年刚公布的OSGI v4.2 规范中新增加了 Blueprint Container 的规范内容。
提到blueprint 就不能不提到spring Dynamic Modules,blueprint 能够觉得是Spring Dynamic Modules版本号的改进和标准化。
SpringDM 1.x版本号实现了Spring Dynamic Modules for OSGi,在Spring Dynamic Modules被标准化为Blueprint Container 规范后,新的SpringDM 2.x 则成为Blueprint的參考实现。
blueprint 的使用实行很类似标准的spring IOC容器,比方相同的使用xml配置文件。仅仅是从ioc 的applictionContext xml变成了Blueprint XML。而Blueprint XML的配置方式和spring 有惊人的相似。
举例,最简单的bean:
基本就是照搬spring IOC的方式。对于熟悉spring的开发者来说无疑是个好消息。起码学习曲线平缓了。
因为是OSGI的标准规范。blueprint 眼下的支持还是不错的,除了上面说的SpringDM外。还有Geronimo Blueprint Container 和 Apache Felix Karaf 都提供了对blueprint的支持。
总结。从上述的发展历程上看,OSGI中的service依赖关系管理方式,经历了从简单原始到逐渐成熟强大的过程,前后经历了大概10年的时间.
很多其它详情