`

OSGI中的service依赖关系管理

    博客分类:
  • OSGI
阅读更多


    众所周知,对于高动态高可扩展的应用,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:

 

   <bean id="accountOne" class="org.apache.geronimo.osgi.Account">

       <argument value="1"/>

       <property name="description" value="#1 account"/>

   </bean>

 

基本就是照搬spring IOC的方式,对于熟悉spring的开发人员来说无疑是个好消息,起码学习曲线平缓了。

 

由于是OSGI的标准规范,blueprint 目前的支持还是不错的,除了上面说的SpringDM外,还有Geronimo Blueprint Container 和 Apache Felix Karaf 都提供了对blueprint的支持。

   
    总结,从上述的发展历程上看,OSGI中的service依赖关系管理方式,经历了从简单原始到逐渐成熟强大的过程,前后经历了大概10年的时间.
分享到:
评论
3 楼 xyz20003 2010-05-25  
多谢多谢,静待佳音。
2 楼 skydream 2010-05-25  
哦,对啊,怎么把这个给忘了,主要是blueprint 我不大了解,好吧,我现在就去磨枪,稍后就加上。
1 楼 xyz20003 2010-05-25  
没涉及blueprint,有些遗憾。

相关推荐

    org.osgi.service.obr-1.0.1.jar

    java运行依赖jar包

    osgi-service:定义跨项目使用的OSGi服务的Java接口

    创建一个数据源(例如,通过连接到诸如PostgreSQL之类的远程RDBMS或例如创建内存中的derby数据库) 使用liquibase创建架构并为DataSource中的数据库提供初始数据要使用此OSGi服务编译代码,请将以下依赖项添加到您...

    Java Application Architecture Modularity Patterns with Examples Using OSGi Part2

    7.11.2 关于管理模块依赖 7.11.3 关于模块重用 7.11.4 关于构建 7.11.5 关于面向对象 7.12 结论 7.13 参考文献 第二部分 模 式 第8章 基本模式 8.1 管理关系 8.1.1 表述 8.1.2 描述 8.1.3 多种实现 ...

    Java Application Architecture Modularity Patterns with Examples Using OSGi Part1

    7.11.2 关于管理模块依赖 7.11.3 关于模块重用 7.11.4 关于构建 7.11.5 关于面向对象 7.12 结论 7.13 参考文献 第二部分 模 式 第8章 基本模式 8.1 管理关系 8.1.1 表述 8.1.2 描述 8.1.3 多种实现 8.1.4 影响 ...

    sisu-guice-peaberry-example:OSGI技术展示

    OSGI应用程序中的Sisu,Peaberry和Guice的示例这是一个示例项目,它使用以下技术来创建动态OSGI应用程序: 根据存在的JSR-330 @Named和@Inject注释,在每个模块中使用Guice自动引导依赖项注入管理服务到OSGI注册中心...

    quickwebframework

    支持所有实现OSGi R4 Service Platform规范的OSGi容器,如:Apache Felix、Equinox OSGi等。 模块化 在程序运行时可以任意安装,启用,停止,卸载WEB模块插件而不用重新启动WEB容器。变化即时生效。 依赖注入支持 ...

    Jetty中文手册

    Jetty JARS和依赖(Dependencies) 启动参数(Start Options) Jetty and JEE6 Web Profile 配置参考 Jetty XML语法(Syntax)–Jetty IOC Configuration Jetty XML用法–Using and Combining Jetty Configurations ...

    Spring-Boot的Dubboxboot-dubbo.zip

    这个及其简单 Mybatis负责较为复杂的查询boot-dubbo-service该项目依赖api和boot-dubbo-infrastructure它要实现api约定的接口,另外依赖boot-dubbo-infrastructure对不同数据表的操作以及对事务的操作boot-dubbo-...

    FOP:提供 Apache:trade_mark: FOP 及其依赖包的 Eclipse 功能

    此存储库提供的功能包含在 OSGi 和 Eclipse 中使用 FOP 所需的捆绑包集合。 #Licence 此功能提供的捆绑包基于 eclipse 更新端 ( ) 和 Orbit P2 存储库 ( )。 因此,它们在 EPL ( ) 下发布或兼容。 以下捆绑包...

    ApkLauncher_legacy

    因为android的静态声明模型(permission, activity, service, action...),某些功能需要主应用的配合才能实现。 如果目标应用的AndroidManifest.xml描述发生变化,宿主平台也需要同时升级; 更加复杂的后台? 对传统...

Global site tag (gtag.js) - Google Analytics