在比较CORBA2.x与CORBA3.x的基础上,简要介绍CCM引入的新特性。
虽然CORBA2.x已成功应用于诸多软件系统的开发,但CORBA2.x仅是一个分布式对象计算模型,并不是一个组件对象模型,OMG组织考虑到CORBA2.x存在的以下问题:
· 缺乏功能分界
在CORBA2.x对象模型中,所有的接口均被视为是面向客户程序的,而缺乏在不同接口实现间进行通信的通用规范。
· 难于扩展对象的功能
在CORBA2.x中,对象只能通过继承(而不是组合)来扩展,应用程序开发人员必须先定义一个IDL接口、实现该接口、并在所有Server中配置该实现。但CORBA IDL的多重继承是有缺陷的,因为有的语言不支持重载;另外,应用程序可能用同一个IDL接口多次发布服务的多个实现或多个实例,但多重继承使得不可能不止一次的发布同一接口,或由客户确定哪一个是最下层的版本。
· 缺乏统一的软件配置、部署规范等
缺乏统一的软件配置、部署规范使得开发人员需要用各自不同的方式,来进行应用系统的初始化及配置、管理,使得整个软件系统变得难于管理与维护。
同时,考虑到组件化中间件的必然趋势,OMG于1999年正式发布了CORBA3.0,CORBA3.0除将IDL2.x扩展到IDL3.0外,还将CORBA组件模型(CCM)引入到了CORBA的世界,使得CORBA成为一种组件中间件技术。
(注:CORBA2.x规范所定义的CORBA仅为一种分布式对象计算技术,有些文章中以CORBA2.x实现为基础讨论CORBA组件技术,并将其与EJB、COM等进行比较,是完全错误的。)
组件中间件技术通过更高层次的抽象定义,弥补了面向对象中间件技术的一些缺陷,定义了组件的虚拟边界、定义了组件的发布方法,以及组件与其他组件和客户端进行交互的方式。同时,组件中间件的定义也支持运行时环境、封装和发布的机制和标准,所有的这些机制和标准都使得了软件组件的重用变得更加简单。通过使用组件中间件,系统可以使用一种“装配的”方式来搭建,而不是使用传统的工程方法,即CORBA2.x中,没有标准支持二进制级别的重用,所有的重用基本是源码级别的,而在CCM中,我们可以以组件为单位在二进制级别上进行实现重用,虽然这在目前来讲还比较困难。
OMG的CCM规范是以EJB为蓝本提出的,并且,为了兼容EJB,CCM还对与EJB的互操作进行了讨论,但目前CCM的商业应用远不如EJB广泛,这一方面与CCM本身的复杂性有关,同时也与CORBA中间件提供商及客户的关注程度有很大关系。
CIAO(Component Intergrated ACE-ORB)是一个基于ACE/TAO的开源CCM实现,它主要面向分布式实时嵌入式(Distributed Real-time Embeded,DRE)应用,是目前所有的CCM实现中相对比较成熟的一个(注:可从http://deuce.doc.wustl.edu/Download.html下载到CIAO的最新版本源代码)。本文将以CIAO0.5为平台,实例讲解如何在CIAO0.5中运用CCM提供的新特性进行CORBA组件的设计。
CCM鼓励通过组合而不是继承来重用组件,为使用组合,组件需要将它的部分操作委派给其它组件。为此CCM规范定义了两种级别的组件类型:基本(basic)组件类型、扩展(extend)组件类型。基本类型组件,主要用于对传统的CORBA分布对象进行组件化实现;扩展组件支持新的接口外观特征,这些新的接口外观特征被称作端口(port),用于支持客户与组件以及组件间的互连,而基本组件类型不支持新的接口外观特性。
CCM支持五种基本端口:刻面/插座(facet/receptacle)、事件源/事件槽(event sources/sink)和属性(attribute)。五种Port的表示方法如下图所示:
此外组件还支持其它一些新特性,包括:
组件可以提供多重对象引用,称之为刻面,用于向客户提供该组件的不同内容的CORBA接口。组件还可以生成一个称之为组件等价接口的单一的对象引用,用于导航至其它组件刻面。
组件内部封装了不同组件刻面的实现,对客户不透明。客户可以通过组件的任何刻面或组件的等价接口导航至组件的其它刻面接口。
在声明组件时,可通过provides关键字来指定组件对外提供的Facet,如:
provides Interface_Name facet_name;
对于每个Facet,都有一个独立的实现类与之对应,该实现类的名称为:
class Interface_Name_exec_i;
通过编译IDL文件,自动化工具会为组件的最终实现类生成一个名为:
get_facet_name
的方法,以便在容器向组件请求Facet服务时返回对应接口实现的实例。
组件接插口提供了组件间互相连接的模型描述,用于描述组件与其它被连接对象(组件)接口之间的关系。组件接插口可以比较简单(如只管理单一的对象/组件引用),也可以较为复杂(管理多重连接的对象/组件引用)。
Receptacle可通过uses关键字来指定,如:
uses Interface_Name receptacle_name;
通过编译IDL文件,自动化工具会在为组件对应的Context类中添加一个名为:
get_connection_receptacle_name
的方法,以便通过容器向另一组件请求对应的Facet接口,以调用Facet提供的方法,完成相应的逻辑处理。
一个Facet可对应多个Receptacle,而一个Receptacle只能有一个对应的Facet。
CCM支持发布/征订(publish/subscribe)式的事件模式。并使用推技术,提供简单的API,支持对CORBA通知(Notification)服务的使用。
组件事件源:
组件事件可以以发射方式(emitter)或发布方式(publisher)向外界发送事件,其中发布方式的组件事件源允许组件发布到事件通道上的事件可以被多个事件征订者所获取。事件客户可通过事件发布器直接访问组件产生的事件流;发射方式的组件事件源则只允许组件发布到事件通道上的事件被单个指定的事件征订者所获取(而其它的征订者则不能获取)。发射方式的组件事件源主要用于组件的配置,一般在初始化或配置时刻被连接到系统的相关单元上,并且不暴露给一般用户。
在声明组件时,可通过publishes或emits来指定Event Source,如:
publishes EventType_Name event_name;
EventType本身是一个值类型,应该以eventtype关键字来声明,如:
eventtype EventType_Name {
public event_attr attr_name;
};
通过编译IDL文件,自动化工具会为组件对应的Context类添加一个名为:
push_event_name
的方法,以便通过容器向其它组件发布通知事件。
组件事件槽:
事件槽定义了组件隐含接收事件的事件类型。外部实体可以连接事件槽提供的事件消费者接口,与其进行关联。与事件源不同,事件槽并不区分特定或一般的事件发送者。通过定义事件槽,组件可以声明其感兴趣的事件类型。
Event Sink可以用consumes关键字来指定,如:
consumes EventType_Name event_name;
通过编译IDL文件,自动化工具会为组件的最终实现类生成一个名为:
push_event_name
的方法,以便在容器向组件转发通知事件时对该事件进行处理。
组件可以向外界显露一个主特征键值。客户可以通过该值查找、创建、删除相关的组件实例。
组件Home是管理组件实例的元类型。组件Home接口提供了管理组件生命周期的接口,以及根据主特征键值关联相关组件实例的功能接口,从概念上理解,组件Home是其相关组件类型实例的管理器。
当组件被装配到组件容器中后,Home对象即被创建。组件的主特征键值通过Home创建并设置,与组件实例进行关联。在CCM规范中,主特征键值可显露给组件客户使用,辅助其确认与相关的组件实例连接。尽管不同的Home类型可以管理同一种组件类型,但在运行时刻,一个组件实例只能被一个Home对象所管理。
Home提供工厂模式的创建操作或查找模式的查询操作来管理组件实例。另外,除了隐式定义的工厂创建或查找操作外,组件开发人员还可以通过扩展的IDL定义其它任意格式的组件创建(factory)或查找(finder)操作,如:
factory create_func_name(arg_list);
finder find_func_name(arglist);
通过编译IDL文件,自动化工具会为对应的组件类生成一个返回值为组件类指针类型的工厂方法和查找方法,而方法的名称是你在IDL文件中定义的名称。
开发人员甚至可以在Home接口中定义其它操作供用户使用,如查询内部接口含义等自省机制的操作。
CORBA组件模型支持组件的属性和配置特征,使得设计者可以在配置组件的过程中通过属性来区分组件接口,或在运行组件的过程中通过属性定义来配置不同的组件实例,以与其它组件实例相区分。
在声明组件时,可以在attribute前添加readonly关键字以表明属性是只读的,如:
readonly attribute Attribute_Type attr_name;
通过编译IDL文件,自动化工具会为组件的最终实现类生成相应的accessor方法和mutator方法,以用于读取和修改属性的值(对于readonly属性,仅有accessor方法),这些方法除可供配置时使用外,在组件实现内部也可使用。
组件的配置过程主要是设置组件属性的过程,在CCM规范中把组件的配置生命周期(Configuration Life Cycle)分为配置阶段(Configuration Phase)和操作阶段(Operational Phase),在配置阶段组件不响应客户端任何请求,由代理调用一些特殊的操作来配置或修改组件的属性集;当配置完毕之后,调用configuration_complete操作标志配置阶段结束,组件进入可操作阶段。
CCM定义了配置(configurator)对象,用于封装组件的属性配置功能,它通过调用一组组件支持的属性定制方法对组件属性进行配置。
组件类型通过继承通用CCM Object接口,以提供CORBA规范定义的组件特征,如接口导航、组件接插口、事件接口等等,而组件Home则继承了CCM Home接口。
CCM规范定义了一种描述语言,组件实现定义语言(Component Implementation Definition Language CIDL),用于定义组件及组件Home和相关抽象状态的实现。CIDL编译器使用CIDL描述生成组件的实现骨架,其中自动集成了大部分基本的组件功能,如接口导航、组件确认、组件查询、组件激活、状态管理、生命期管理等等。组件的实现者通过扩展这些实现骨架(放入业务逻辑),实现最终的组件。
CIDL是持久状态定义语言(Persistent State Definition Language PSDL)的超集,它允许描述组件内部状态与外部抽象存储类型的联系,组件实现框架CIF和组件容器则可以通过协作自动对组件的持久状态进行管理。
一个组件类型是一组基于IDL组件定义以及其它相关结构描述信息的集合,它具有特定的状态和特征值,并封装了内部的表示和实现。
组件实现以组件包的形式存在,它包含了一种或多种组件实现的可执行代码,以及描述该组件类型的元数据。组件包有两种隐含的使用方式,即在组件应用开发时,由应用组装工具对其进行定制和安装;或在运行时,直接通过配置工具将其装载入当前可运行的组件容器中,被组件应用的客户所使用。
组件在CORBA组件容器中被初始化和“存活”,不同的组件类别将使用到不同类别的组件容器。
组件的开发步骤可大致分为以下几步:
1. 组件应用的分析/设计
2. 组件定义(基于IDL/CIDL语言)
即定义接口和异常及需要用到的基本数据结构,并利用IDL3.x新增的CCM关键字(如component、supports、provides、uses、publishes、emits、consumes)来“组装”组件,并定义组件的home接口以声明用于创建组件的factory方法;
3. 组件实现(用户实现业务逻辑功能)
4. 组件打包:
组件打包文件包括组件实现和组件描述。一个完整的组件是可配置的,具有自描述能力的软件包(package)。组件包可以在运行时被安装或配置到组件应用中立刻为客户提供服务,也可以在设计时通过开发环境“可视的”进行装配,并生成装配信息。被打包的组件实现和组件描述等内容将以组件存档文件的形式进行存储。
5. 组件组装:
组件组装阶段可以对多个组件进行定制,连接(与其它组件)和分割,并形成组件组装存档文件。组件组装文档描述了一组(可以是已定制了的)物理组件集合及其之间的关系描述,包括定义组件实例之间的关系,配置组件的初始属性/状态,描述与其它组件的连接关系等内容。组件组装文档既可以直接进行配置,在运行时可被一个组件容器或位于不同主机的多个组件容器所动态装入和初始化,也可以继续被构造成更复杂的组装文档。
6. 组件的配置与安装:
提供配置/安装服务,可以将打包好的组件配置安装到网络上的特定主机上运行。
7. 组件实例激活与运行:
一旦组件被配置和安装成功,组件实例通过标准的CORBA ORB机制被激活运行并提供相应的服务。
下一篇文章将以一个实例,详细讨论基于CIAO的CCM组件的开发过程。
1. Sharplog. CCM简介. http://corbatime.diy.myrice.com/article/ccm_intro.htm
2. OMG CCM Implementers Group and MARS PTF & Telecom DTF, CORBA Component Model Tutorial, http://www.omg.org/docs/ccm/02-04-01.ppt, April, 2002.
3. Object Management Group, Inc. CORBA Component Model Specification, v4.0, http://www.omg.org/cgi-bin/apps/doc?formal/06-04-01.pdf, Apr, 2006
4. Douglas C. Schmidt and Steve Vinoski, Object Interconnections: The CORBA Component Model: Part 1, Evolving Towards Component Middleware, C/C++ Users Journal, February, 2004.
5. Douglas C. Schmidt and Steve Vinoski, Object Interconnections: The CORBA Component Model: Part 2, Defining Components with the IDL 3.x Types, C/C++ Users Journal, April, 2004.
6. Bala Natarajan, Douglas C. Schmidt, and Steve Vinoski, The CORBA Component Model Part 3: The CCM Container Architecture and Component Implementation Framework, C/C++ Users Journal, September, 2004.
7. Bala Natarajan, Douglas C. Schmidt, and Steve Vinoski, The CORBA Component Model Part 4: The CORBA Component Model Part 4: Implementing Components with CCM, C/C++ Users Journal, October, 2004.