OSGI中的service依赖关系管理

众所周知,对于高动态高可扩展的应用,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依赖管理机制,是最简单直接的方式,其基本原理非常简单,标准的注册/查找:

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依赖对于开发者来说完全是个重体力活: 很重要,经常要做,容易出现错误, 出错时不容易测试。而且,这些工作都不是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是一个服务器组件运行时,目标在于简化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年的时间.

更多详情

OSGI中的service依赖关系管理,布布扣,bubuko.com

时间: 2024-11-25 06:55:37

OSGI中的service依赖关系管理的相关文章

MyEclipse中的Maven依赖关系管理

1. Maven支持唯一依赖关系 Apache Maven是一个软件项目管理的综合工具.根据项目对象模型(POM)的概念,Maven可以管理一个项目的依赖关系.构建.报表以及信息中心的部分文档. 依赖关系管理是Maven最知名的功能之一,也是Maven最擅长的领域之一,但是通常只利用这个功能是不可能的.几乎所有的方式都需要您去配置一个基于Maven的项目.添加和配置Maven插件.处理文件和goals.同时MyEclipse完全支持最先进的Maven功能,如果您只想对依赖关系进行管理,那么创建一

Gradle用户指南(章8:依赖关系管理基础)

章8:依赖关系管理基础 本章将介绍一些gradle依赖关系管理的基础 什么是依赖关系管理? 简略的说,依赖管理是由两部分组成的.首先,gradle需要知道你要构建或者运行的项目,以便找到它们.我们将这些导入的文件视为项目的依赖.第二,gradle需要构建或者打包你的项目产品.我们将这些导出的文件视为项目的发布.下面,让我们在细节上更多的了解这两个方面. 大部分项目都不是完全彻底的独立的.它们需要其他项目的构建文件,以便编译.测试等等.例如,为了在我的项目中使用Hibernate,当编译我的源文件

在SQL Server中查看对象依赖关系

原文 在SQL Server中查看对象依赖关系 Viewing object dependencies in SQL Server Deleting or changing objects may affect other database objects like views or procedures that depends on them and in certain instances, can “break” the depending object. An example can

DolphinScheduler工作流调度引擎 致力于解决数据处理流程中错综复杂的依赖关系

DS是什么 Apache DolphinScheduler是一个分布式去中心化,易扩展的可视化DAG工作流任务调度系统.致力于解决数据处理流程中错综复杂的依赖关系,使调度系统在数据处理流程中开箱即用.DolphinScheduler曾用名为"EasyScheduler",由易观开发,美国时间2019年8月29日,正式通过顶级开源组织Apache基金会的投票决议,以全票通过的优秀表现正式成为Apache孵化器项目.由于名称已在国外某App使用,经社区讨论与投票后改名为DolphinSch

windows下安装php依赖关系管理工具composer

1.首先安装php,配置环境变量 2.在项目代码目录下执行 php -r"eval('?>'.file_get_contents('https://getcomposer.org/installer'));",若出错可尝试将https改成http

(4.27)查看存储过程中的依赖关系

关键词:查看存储过程中引用的表,查看表在哪些存储过程中出现过 很多时候需要找到存储过程所依赖的对象.博客描述了一种在SQL服务器中查找存储过程依赖关系的方法. 以下查询创建存储过程. 1 2 3 4 5 6 7 8 9 10 11 IF object_id('usp_getpersonaddress') is not null drop proc usp_getpersonaddress GO Create procedure usp_getpersonaddress AS SELECT pp.

Linux软件间的依赖关系(转)

Linux中的软件大部分是零碎的,其粒度比windows的小很多,软件之间的依赖关系很强烈,下面是自己的一些理解: 一.Linux中的软件依赖Linux中的软件依赖关系成一颗拓扑树结构,比如A直接或间接依赖B,那么B就不可能直接或间接依赖A.试想从时间上A.B必然有一个先出现,而先出现的不可能依赖于后出现的:并且如果A与B互相依赖则就是“鸡与蛋”的问题,因此必然有一个先出现而另一个依赖于先者. 二.Linux的软件安装与卸载(1)安装软件A必须率先安装A依赖的所有软件:卸载软件A则必须率先卸载依

Prism 文档 第三章 管理组件之间的依赖关系

                                                                      第3章:管理组件之间的依赖关系 基于Prism库的复合应用程序可能包含许多松耦合的类型和服务.他们需要提供内容和接收基于用户行为的通知.因为他们是松散耦合的,他们需要一种方式进行互动和相互沟通来提供所需的业务功能. 为了集中这些不同的块,基于Prism库的应用程序依赖于依赖注入容器.依赖注入容器通过提供设施去实例化类的实例和管理他们基于容器配置的寿命来减少对

Prism4 文档翻译系列---第3章 管理组件间的依赖关系

基于Prism类库的应用程序可能是由多个松耦合的类型和服务组成的复杂应用程序,他们需要根据用户的动作发出内容和接收通知进行互动,由于他们是松耦合的,他们需要一种方式来互动和交流来传递业务功能的需求. 为了将这些零散的模块组合在一起,基于Prism的应用程序使用了一个依赖注入容器,依赖注入容器通过基于容器的配置提供实例化类对象并且管理它们的声明周期减少了对象之间的依赖耦合关系.在创建对象时,容器将其所需要的依赖全部注入其中.如果这些依赖还没有被创建,容器将会首先创建并解析依赖所需要的对象或者它的依