OSGi的CM就是Configuration Admin Service,是用于管理Bundle属性、并在属性发生变更时通知相应的Service,可以看出,这是保持OSGi动态性的很关键的一个服务,毕竟配置属性的修改是会发生的,象修改了Http的端口呀等,但又不希望修改这些属性后需要重启才能生效,那么CM是一个不错的选择,使用CM时无需关心属性具体怎么存储这些问题,而在属性修改后CM也会自动通知相关的service。
通常在系统的属性管理上,我们的需求通常是在一个统一的界面上对系统的相关属性进行统一的配置,保存后则希望能通知相应的服务,这里面的属性自然有些是公用的,有些是某些模块专用的,既然基于CM来实现这样的需求,首先来看看基于CM需要怎么去做,这是基于CM的统一管理系统属性的典型的序列图:
其中ConfigurationAdminService、ManagedService均为CM中定义的规范的服务接口,而ConfigManageAction就是用于实现统一管理属性配置的web响应接口了,根据上图可以看出,通过调用ConfigurationAdminService的getConfiguration方法可以获取到Configuration对象,通过这个对象可以获取到配置的属性集合,而通过Configuration对象的update方法就可以更新属性了,ConfigurationAdminService在更新属性时将异步的调用系统中对外提供了ManagedService的服务的update方法,该方法的参数即为更新的属性的集合。
首先要说明下CM对于属性是怎么进行存储的,CM对于属性的存储是根据服务注册时提供的service.pid的值(必须是唯一的)以及Bundle Location(Bundle的地址)构成key来存储其属性的,按照这样的过程,在维护属性时自然也要以这个为Key来进行操作,同样的,在通知属性更新时CM也是根据这个key的值来决定的,但实现ManagedService的服务只能传入service.pid这个值,Bundle Location的值CM将自动的获取该服务所属的Bundle的Location,这看似设计的很好,但同时在应用层面则带来了一个问题,后面将会讲到。
假设我们的需求是这样的:
1、A Bundle中的PortService的port属性需要管理,BookService的bookcount属性需要配置;
2、B Bundle中的PortConfigService的port属性需要管理,MenuService中的menucount属性需要配置;
3、其中A Bundle中的PortService所需的port和B Bundle中的PortConfigService所需的port属性是相同的;
4、属性统一在C Bundle中通过提供web界面的管理方式来实现,在属性发生变化时要通知相应Bundle的Service。
那么根据上面对于CM的讲解我们来实现这个需求:
1、PortService、BookService、PortConfigService、MenuService均需实现ManagedService接口,ManagedService接口中只有一个方法update(Dictionary props),当service关注的属性被更新时CM将会自动的通知,然后服务根据属性自行的做出相应的处理;
2、PortService、BookService、PortConfigService、MenuService对外提供ManagedService接口,在注册时提供service.pid属性的值,这个值必须是唯一的,假设分别为a.port、a.bookservice、b.port、b.menuservice;
3、实现ConfigManageAction,配置页面上自然是只有port、bookcount和menucount三个属性需要配置的了,由于CM是采用service.pid加上Bundle的Location来构成key的,而在通知属性更新上也是根据这个key来决定,那么这其实也就已经意味着ConfigManageAction在管理这几个属性时必须带上相应的Bundle的Location了,这是不太合理的地方,首先要获取Bundle的Location是比较麻烦的事,其次是这样也就意味着ConfigManageAction是必须知道当属性变更时需要通知到哪些Bundle的,如果将来增加一个Bundle的服务需要监听某已经存在的属性的话,就必须要修改ConfigManageAction的代码,当然,这和注册的服务监听的server.pid的属性必须唯一也有关,也就是说CM其实只是一个基于Event的一对一的订阅/发布模型,这就导致了在维护一个port这样的公共属性的时候竟然要在A Bundle的PortService和B Bundle的PortConfigService中各存一份,OSGi联盟对于此的解释是出于安全问题的考虑,所以在CM的设计上采取了加上Bundle Location做为Key的原因。
在这样的情况下,也就导致了ConfigManageAction变得复杂了......
CM在这块设计上欠缺对于应用级属性(共享配置属性)上的考虑绝对是有待商讨的,现在只能是在各个Bundle中各自维护一套,同时在各自Bundle中提供一个ConfigManageService这样的服务来更新当前Bundle中的属性,这样才能解决Bundle Location的那个问题,在目前的情况下就没法构成共有属性的维护方式了,如果是公有属性变化的话也就只有在ConfigManageAction中调用相关的多个Bundle的ConfigManageService来完成属性的修改了,这样的话存储和动态的通知仍然交由CM去完成了。
关于模块的耦合上只有个小小的想法讨论下,就是做为设计师你能否很快的告诉别人搭建你其中的一个模块的工程需要哪几个模块的支撑,或者最好就是运行检验你其中的一个模块的功能需要哪几个模块来支撑,当然,这个在基于OSGi的系统更容易来做到,不过这个确实是设计时很关键的一个地方,这既反映了系统中模块的耦合性,更体现了系统的扩展性以及系统的组装耦合上是否合理。
分享到:
相关推荐
第三部分由原型构建转向实际的产品开发,主要介绍了OSGi和Equinox中用来构建成熟的OSGi应用必不可少的API——服务器端、声明式服务和发布工程,以及如何用它们来解决实践中的一些问题;第四部分呈现了动态性的最佳...
osgi介绍osgi介绍osgi介绍osgi介绍osgi介绍osgi介绍osgi介绍osgi介绍osgi介绍osgi介绍
接下来,你将掌握一些用于创建具有特殊模块化、高效性和可维护性系统的最佳实践和技巧。你将了解所有的OSGi声明式服务,以及如何通过这些服务来解决各种现实问题。最后,你会发现所有这些都在本书所提供的完整案例...
OSGi与Equinox 创建高度模块化的Java系统 This first part of the book introduces OSGi and Equinox, Eclipse’s implementation of the OSGi standard. Chapter 1outlines the history and context of OSGi. Its ...
OSGi与Equinox 创建高度模块化的Java系统 第5章 源码。 按照书中描述编写,导入Eclipse可以直接运行。
《osgi与equinox 创建高度模块化的java系统》第6章声名式服务代码
OSGi与Equinox 创建高度模块化的Java系统,分享给所有需要的人
第五章源码,主要是将gps和安全气囊作为服务发布出来,具体的实现不在对其他bundle可见。
OSGi与Equinox 创建高度模块化的Java系统 第4章完整源码。 网上已很难找到源码,是按照书中描述编写的,可直接导入Eclipse运行。
C#版OSGi模块化框架,本代码来源自Github
国内第一本OSGi图书OSGi国内推广者林昊多年经验的结晶涵盖OSGi从入门到深入的知识体系引领OSGi国内研究和普及本书基于作者多年使用OSGi的经验而编写,涵盖了OSGi从入门到深入的知识体系,从OSGi的简介开题,介绍OSGi...
osgi框架介绍,想了解osgi框架开发模式的可以下下来看看,里面包含几个pdf,比较基础和详细
是一本适合新接触OSGI开发学习的一本很好的书,本书介绍了Equinox, Spring-DM和Felix这三个常用的OSGi容器的使用、开发、以及WebApplication的开发部署;介绍了OSGi的规范和Core Framework和Layer。包含书中的用例源...
《Java应用架构设计 模块化模式与OSGi》PDF版本下载
Java应用架构设计 模块化模式与OSGi
osgi与equinox 创建高度模块化的java系统 第6章源码 包括ServiceTracker和DeclaredService(DS)实现,导入Eclipse可以直接运行。
spring-osgi 入门手册和代码 spring-osgi 入门手册和代码 spring-osgi 入门手册和代码 spring-osgi 入门手册和代码
OSGI技术介绍,自己公司的培训文档,非常全面的描述了OSGI
Java应用架构设计模块化模式与OSGi