`

osgi服务模型

    博客分类:
  • osgi
阅读更多

基于 OSGi 服务模型实现组件之间松耦合通信

 

 

简介: OSGi Service Layer 所定义服务模型是以发布 (Publish) 发现 (Find) 和绑定 (Bind)为基础操作的动态协作合作模型。所谓的服务 (Service) 就是标准的 Java 对象向服务注册表 (Service Registry) 注册的一个或者多个接口 (interface)。 Bundle 可以向服务注册表注册服务,查询服务并使用它们。本文所要讨论的是基于 OSGI 动态服务模型的 Event Admin Service,通过使用 Event Admin Service,开发者可以开发类似于 JMS 的,基于消息的松耦合应用。

OSGi Service Layer 简介

在开始我们的正式讨论之前 , 让我们花些时间来回顾一下这些预备知识。

简单来讲,OSGi 服务层 (OSGi Service Layer) 是一个构建在 Java 之上的 SOA 平台,它定义了一个动态协作的服务模型,该模型以发布、绑定、发现为基本操作,分离契约 ( 接口 ) 与实现。Bundle 可以向服务注册表注册服务,查询服务并使用它们,如图 1 所示。


图 1. OSGi 服务模型 .
 

Bundle dw.sample.service.provider 实现服务,并把它注册给服务注册表,Bundle dw.sample.service.consumer 通过向服务注册表查询,获得该服务,并使用它。

OSGi 服务层技术范畴涉及以下的几个核心概念:

  • 服务 (Service),即实现契约的 Java 对象 (POJO),该对象可以通过一个或者多个接口向服务注册表注册,别的 Bundle 可以通过服务注册表发现他们。
  • 服务注册表 (Service Registry),保存所有服务注册信息。
  • 服务引用 (Service Reference),指向服务的引用,它们并不是真正的服务对象,Bundle 使用 Bundle Context 通过该引用获得真正的服务。
  • Service Registration,在 Bundle 向服务注册表注册一个服务后,会获得一个 Service Registration,Bundle 可以用 Service Registration 更新服务属性,反注册服务等。
  • 服务事件 (Service Event), 当服务对象被注册、修改、反注册时,相应的服务事件会产生。
  • 服务监听者 (Service Listener),用于侦听所发生的服务事件。

OSGi 服务编程

在本节,我们先来看一个 OSGi 服务的例子。

清单 1 定义了我们的服务契约,清单 2 实现了清单 1 定义的借口。


清单 1. IQuoteService 接口
				
 public interface IQuoteService { 
  String getQuote(); 
 } 


清单 2. IQuoteService 接口实现
				
public class QuoteService implements IQuoteService { 

	 @Override 
	 publicString getQuote() { 
		 return"Hi, you are using quote service."; 
	 } 

 } 

接下来,我们需要发布我们所定义的服务,如清单 3 所示:


清单 3. 发布服务
				
 public class Activator implements BundleActivator { 
       ……
  public void start(BundleContext context) throws Exception { 
    IQuoteService service = new QuoteService(); 
    
    Dictionary<String,String> properties = new Hashtable<String,String>(); 
      
    context.registerService(IQuoteService.class.getName(), service,properties); 
  } 
       ……
 } 

如清单 3 所示,我们使用 IQuoteService 接口,通过 Bundle Context 注册了我们服务,properties 是服务附带的属性。

清单 4 给出了另外一个 Bundle 消费该服务的例子。


清单 4. 消费服务
				
 public class Activator implements BundleActivator { 
       ……
  public void start(BundleContext context) throws Exception { 
    ServiceReference reference = 
          context.getServiceReference(IQuoteService.class.getName()); 
    if(null != reference ) { 
      IQuoteService service = (IQuoteService) context.getService(reference); 
            if( null != service) { 
              System.out.println(service.getQuote()); 
            } 
    } 
  } 
       ……
 }    

如清单 4 所示,使用 Bundle Context, 通过 IQuoteService 获得服务引用,进而通过该服务引用获得真实的服务对象,并消费它。

从上面的例子可以看到,实质上,服务的提供者与服务的消费者之间是存在耦合关系的,在清单 4 中,服务的消费者使用了 IQuoteService 接口定义,也就是说,服务的消费者实现依赖于服务提供者的接口定义,虽然这种依赖通过契约与实现相分离得到了弱化。图 2 给出了调用序列图。



 

通过本节的介绍,相信读者对 OSGi 服务发布、查询、使用有了比较全面的了解。基于这些基本的概念,我们接下来讨论如何使用 OSGi 提供的 Event Admin 服务,实现 Bundle 的松散耦合通信。


基于 Event Admin 服务的 Bundle 间通讯

OSGi 的 Event Admin 服务规范提供了开发者基于发布 / 订阅模型,通过事件机制实现 Bundle 间协作的标准通讯方式,如图 3 所示:


图 3. Event Admin 服务模型 .
 

事件发布者使用 Event Admin 服务发送基于主题 (Topic) 的事件,任何对某一主题感兴趣的事件订阅者都会收到该事件,并且做出相应的反应。

如何发布事件

我们遵循以下的步骤,通过 Event Admin 发布事件:

  1. 获得实现了 org.osgi.service.event.EventAdmin 接口的 Event Admin 服务引用。
  2. 拟定事件的主题。
  3. 指定事件所携带的 key/value 属性集。
  4. 使用 Event Admin 提供的 postEvent 或者 sendEvent 方法发布事件,postEvent 使用同步的方式发布事件,即:等到所有的事件订阅者响应了该事件,方法调用返回,而 sendEvent 使用异步的方式发布事件。

清单 5. 发布事件
				
 public class EventPublisher { 
  ……
  public void publish() { 
    if (getEventAdmin() != null) { 
      //post event, the topic is "com/ibm/dw/test1", 
      //the event properties: property1 = 1 
      getEventAdmin().postEvent(new Event("com/ibm/dw/test1",getEventProperties("1"))); 
      getEventAdmin().postEvent(new Event("com/ibm/dw/test1",getEventProperties("2"))); 
      getEventAdmin().postEvent(new Event("com/ibm/dw/test2",getEventProperties("1"))); 
    } 
  } 

  protected Dictionary<String,String> getEventProperties(String property1Value) { 
    Dictionary<String, String> result = new Hashtable<String,String>(); 
    result.put("property1", property1Value); 
    return result; 
  } 
        ……
 } 

 public class Activator implements BundleActivator { 
  ……
  public void start(BundleContext context) throws Exception { 
    ServiceTracker serviceTracker = 
              new ServiceTracker(context,EventAdmin.class.getName(), null); 
    serviceTracker.open(); 
    //using the service tracker to get the Event Admin service. 
    EventAdmin eventAdmin = (EventAdmin)serviceTracker.getService(); 

        if (null != eventAdmin) { 
      getEventPublisher().setEventAdmin(eventAdmin); 
      // publish events. 
      getEventPublisher().publish(); 
    }  
  } 
  ……

 } 

对于事件的主题,原则上应该遵循一定的命名规范,如清单 5 所示,第一个被发布的事件主题是 com/ibm/dw/test1,其规则与命名 Bundle 名字规则相类似,这样的命名规则容易让消费者订阅,不容易产生冲突,混淆。

如何订阅事件

遵循以下的步骤,来订阅被 Event Admin 发布的事件:

  1. 确定你想要订阅那些主题事件,支持通配符。
  2. 如果需要,根据事件的属性确定事件的过滤原则。
  3. 发布实现了 org.osgi.service.event.EventHandler 接口的你的事件订阅服务,以便当你感兴趣的事件发生后,Event Admin 能通知到你。

事件订阅代码如清单 6 所示。


清单 6. 订阅事件
				
 public class EventSubscriber implements EventHandler { 
  public void handleEvent(Event event) { 
    System.out.println(String.format( 
    "Event Subscriber '%s' handled event on topic           '%s':"+
     " Value of 'property1' = %s",             getHandlerName(), 
    event.getProperty(EventConstants.EVENT_TOPIC), 
    event.getProperty("property1"))); 
  } 
       ……
 } 
 public class Activator implements BundleActivator { 
  ……
  public void start(BundleContext context) throws Exception { 
    //Register event subscriber 1 to subscribe all the events 
    //whose topic is equal to "com/ibm/dw/test1". 
    context.registerService(EventHandler.class.getName(),  
                new EventSubscriber("Subscriber 1"),  
                getHandlerServiceProperties("com/ibm/dw/test1"));  
          
    //Register event subscriber 2 to subscribe all the events 
    //whose topic wilcards matches with "com/ibm/dw/*"
    //and the event's property1 property is equal to 2. 
    context.registerService(EventHandler.class.getName(),  
                new EventSubscriber("Subscriber 2"),  
                getHandlerServiceProperties(new String[] { "com/ibm/dw/*" },  
                        "(property1=2)"));  
  } 

  protected Dictionary<String, String[]>  getHandlerServiceProperties(String... topics) { 
    Dictionary<String, String[]> result = 
    new Hashtable<String, String[]>(); 
    result.put(EventConstants.EVENT_TOPIC, topics); 
    return result; 
  } 

  protected Dictionary<String, Object> getHandlerServiceProperties( 
      String[] topics, String filter) { 
    Dictionary<String, Object> result = 
    new Hashtable<String, Object>(); 
    result.put(EventConstants.EVENT_TOPIC, topics); 
    result.put(EventConstants.EVENT_FILTER, filter); 
    return result; 
  } 
  ……
 } 

示例代码的运行结果如清单 7 所示:


清单 7. 运行结果
				
 Event Subscriber 'Subscriber 1' handled event on topic 'com/ibm/dw/test1':
                 Value of 'property1' = 1 
 Event Subscriber 'Subscriber 1' handled event on topic 'com/ibm/dw/test1':
                 Value of 'property1' = 2 
 Event Subscriber 'Subscriber 2' handled event on topic 'com/ibm/dw/test1': 
                Value of 'property1' = 2 

对这个结果,在这里稍微解释一下:对于 Subscriber 1,由于它指明处理所有主题为 com/ibm/dw/test1 的所有事件,所以 EventPublisher 发布的前两个事件它都收到了。而对于 Subscriber 2,由于它指明只接收主题匹配 com/ibm/dw/*,且 property1 属性等于 2 的事件,所以 Subscriber 2 只处理了 EventPublisher 发布的第二个事件。而 EventPublisher 发布的第三个事件,由于不满足条件,没有被任何一个 Subscriber 处理。

关于这部分的源代码,读者可以从本文后面的资源列表中下载。

从这个例子中可以看到,发布事件的 Bundle 与订阅事件的 Bundle 之间没有任何的相互依赖关系,它们之间以 Event Admin 服务为中间人 (Broker),以事件 (Event) 为消息载体,进行 Bundle 间的松散协作。

基于 Event Admin 服务的 Bundle 通讯,我们总结如下几点:

  1. OSGi Event Admin 的事件模型,与传统的 JMS 相比,OSGi Event Admin 事件不是持久化的,也就是说,通过 Event Admin 发布的事件只在本次应用会话期间存在,当 OSGi 应用重新启动后,所有的未处理的事件将全部丢失。
  2. 由于 OSGi 服务的动态特性,使用该模型时,必须考虑到以下的情况:由于订阅事件的 Bundle 可以在任意运行时刻注册实现了 org.osgi.service.event.EventHandler 接口的事件订阅服务,所以开发者不能期望订阅者总能够收到在本次会话期间事件发布者发布的所有事件,一个典型的情况是,如果在发布者发布事件的时候,订阅者服务尚未注册,其结果是,该订阅者错过这次事件。
  3. 在 Equinox 环境下,如果想使用 Event Admin 服务,需要额外从 www.eclipse.org 下载具体的 Event Admin 服务 Equinox 实现 org.eclipse.equinox.event Bundle, 在默认的情况下,org.eclipse.equinox.event Bundle 并没有包含在 Equinox 的 SDK 里。

小结

OSGi 服务层所提供的服务模型,其动态发现、动态绑定、契约与实现相分离等特性,可以帮助开发者实现组件之间依赖保持在接口之间,而与具体实现代码相对松散的应用逻辑。在此基础上 OSGi 提供了基于事件的 Event Admin 服务。Event Admin 服务本质上是基于消息的发布 / 订阅机制,对于 OSGi 的开发者来说,Event Admin 服务可以帮助他们实现组件间更为松散的,不依赖任何接口定义的协作逻辑。

<!-- CMA ID: 458836 --><!-- Site ID: 10 --><!-- XSLT stylesheet used to transform this file: dw-article-6.0-beta.xsl -->
  • 大小: 98.3 KB
  • 大小: 79.2 KB
  • 大小: 27.1 KB
分享到:
评论

相关推荐

    论文研究-基于OSGi的两层服务模型.pdf

    基于OSGi的两层服务模型正是针对ROSGi的这些缺点,从一种新的视角来看待分布式环境中的OSGi平台,将每一个独立的OSGi平台视为一个能够提供远程服务并可能要获取其他远程服务的构件,使用面向服务的构件模型的方式来...

    基于 OSGi 的面向服务的组件编程

    基于 OSGi 的面向服务的组件编程呆呆呆呆呆呆地

    OSGi.NET框架 Documentation

    本文档主要针对OSGi.NET模块化框架使用进行了描述 ...6.组件的通信支持:组件间通过面向服务的编程模型来达到组件间通信、调用的目的 7.组件的扩展支持:组件提供了扩展点及其扩展来满足某个组件的扩展性支持

    一种基于服务构件模型的自适应方法 (2011年)

    oriented Service Component Method),该方法以OWL-based Web Service Ontology扩展的OSGi服务模型为基础,通过感知运行时外界的变化且根据相应的策略动态调整软件体系结构,并通过应用实例验证了基于本体的软件自...

    OSGi中基于ASM的动态服务更新模型

    本文提供了一种基于OSGi的面向服务系统的基于ASM的高级语义模型,并支持服务动态更新。 该模型不仅提供了优化方法,还提供了指定OSGi约束的最终模型。 生成的形式模型可以以多种方式应用。 首先,它可以检查或比较...

    OSGI框架实战

    OSGI框架实战 一. 序..5 ...8.2. 面向服务的组件模型设计....85 8.3. 动态性设计...85 8.4. 面向接口的开发..85 九. OSGI资源..87 十. OSGI框架前瞻..88 十一. OSGI带来的遐想..89 十二. 参考文献..90

    Introduce.OSGi.ppt

    OSGi 技术是面向Java的动态模型系统。OSGi服务平台向Java提供服务,这些服务使Java成为软件集成和软件开发的首选环境。 Java提供在多个平台支持产品的可移植性。OSGi技术提供允许应用程序使用精炼、可重用和可协作的...

    Spring动态模型参考指南1.0.1 osgi

    Spring动态模型参考指南1.0.1 osgi

    OSGi.in.action.ppt

    OSGi 技术是面向Java的动态模型系统。OSGi服务平台向Java提供服务,这些服务使Java成为软件集成和软件开发的首选环境。 Java提供在多个平台支持产品的可移植性。OSGi技术提供允许应用程序使用精炼、可重用和可协作的...

    OSGi specification 4

    OSGi的体系架构是基于这样一个模型的:经营者管理着一个潜在的巨大的服务网络平台。OSGi规范假设这个服务平台是完全被这个经营者控制,并且经营者使用该服务平台去运行来自不同服务提供者提供的服务。然而这只是一个...

    spring osgi 规范 中文版

    它提供一个轻量级的容器,依赖注入、aop、可插接的服务抽取,这些使得非侵入式的编程模型成为可能。OSGi提供了一个动态应用程序的执行环境,在这个环境中组件(bundles)可以在运行中被安装、更新、删除。它同时也...

    OSGI 实战教程

    目前国内为数不多的OSGI教程 讲述OSGI的基本知识 以及实际开发

    OSGi原理与最佳实践.pdf

    OSGi(Open Service Gateway Initiative)技术是面向Java的动态模型系统。

    论文研究-基于OSGi架构的面向服务组件编程 .pdf

    基于OSGi架构的面向服务组件编程,赵林虎,,OSGi(Open Services Gateway Initiative,开放服务网关协议) 提供了一个面向服务组件编程模型。通过OSGi 框架可以轻松构建组件,同时组件与组件之

    Spring-OSGI 1.0 M3 中文手册

    Spring是一个全功能的Java/JEE应用框架。它提供了一个轻量级的容易和一个用于依赖注入的非侵入式编程模块,AOP功能和便携式服务抽取。...对于使用OSGI平台特性的企业级开发者来说这些都是简单和熟悉的编程模型

    Java Application Architecture Modularity Patterns with Examples Using OSGi Part2

    Java应用架构设计:模块化模式与OSGi 英文版 中文版介绍: 全球资深Java技术专家的力作,系统、全面地讲解如何将模块化设计思想引入开发中,涵盖18个有助于实现模块化软件架构的模式 中文目录: 第一部分 模块化...

    OSGi Java 编程资料

    学习OSGi时搜集的资料 OSGi(Open Services Gateway Initiative,开放服务网关协议)提供了一个面向服务组件的编程模型,基于 OSGi 编程,具有模块化,标准化,面向服务,动态性,易复用,易扩展,易部署等诸多优点

    企业OSGI实践

    如果你以前用过JEE(java Enterprise Edition)的话,你可以将Enterprise OSGI看成是一种新的,集合了OSGI特性的企业应用开发模型。如果你更了解OSGI的话,你可以将Enterprise OSGI看成是一种集合了JEE和其它企业...

    osgi.enroute:OSGi enRoute项目提供了OSGi应用程序的编程模型。 该项目包含为OSGi enRoute基本配置文件提供API的捆绑包,以及为OSGi enRoute项目提供的捆绑包。 基本概要文件建立了一个运行时,其中包含可以用作应用程序基础的最小服务集。 捆绑包是简单的实现,可用于为较小的应用程序运行enRoute,并提供示例如何更彻底地实现它。 此回购中也有示例

    基于最新的OSGi最佳实践和R7规范,enRoute教程首先对声明式服务进行了全面的动手介绍,然后继续探索OSGi的微服务和React系统的独特而强大的方法。 该存储库包含enRoute教程的代码,并且还为OSGi R7参考实现定义了...

    aspecio:Aspecio,用于OSGi服务的AOP代理

    Aspecio,适用于OSGi的AOP代理 Aspecio是为OSGi R6提供AOP代理的“微框架”。 它为您的应用程序带来了面向组件的编程和面向方面的编程的混合。 通过Aspecio,您可以定义方面,以后可以选择这些方面以向组件添加行为...

Global site tag (gtag.js) - Google Analytics