着面向服务架构(Service-Oriented Architecture)使用率的增长,由Web服务API(目前最流行的SOA实现技术),如Java中的JAX-RPC或.NET中的Web服务扩展(Web Services Extension,WSE)API,所提供的抽象级别对于有效实现SOA越来越显得力不从心:
目前尝试通过定义SOA编程模型(其中,从其他技术中借用了很多元素)来提高API的抽象级别,这样可解决当前API集合中的一些问题。编程模型的目标是,降低应用程序开发者直接处理中间件或Web服务特定API时面临的复杂度。通过从业务代码中移除大部分的通信支持,并将它们隐藏在编程模型抽象/实现之后,这样可以获得以下好处1:
Web服务调用框架(Web Services Invocation Framework,WSIF)2 3是创建这种模型的最早尝试之一,最初由IBM发起,目前是Apache基金的一部分。
WSIF试图将服务使用模型与基于WSDL的服务定义结合起来——WSIF API直接支持WSDL语义。这使得WSIF能为使用不同传输协议的不同服务实现提供统一的调用模型。尽管WSIF本身从来没有获得广泛地采用,但它作为服务调用的API,被很多BPEL引擎使用,如IBM的WPC和Oracle的BPEL管理器。
对于SOA实现来说,以下3个模型是目前最流行的:
通过支持无缝的服务编排(orchestration)和许多对于成功实现SOA必需的模式,这些编程模型试图超越简单的服务调用,并期望提供更多的功能。它们同样也是实现企业服务总线(Enterprise Service Bus,ESB)的基础。在本文中,我们将对每个编程模型进行简单的概览。
WCF是微软最新的面向服务架构的编程模型实现,支持丰富的技术集合,用于“创建,消费,处理和传送消息”。Indigo计划与下一版的Windows Vista一起发布。
WCF将服务定义为暴露一组端点(endpoint)的程序,每个端点是3个主要元素的组合5:
通过允许使用包含不同绑定和端点契约(QoS)的复合端点(multiple endpoints)来暴露相同的功能(服务),这些定义有效地扩展了基于WSDL的服务定义。
Indigo编程模型的基础之一是使用OO实现SOA编程的所有方面。
| SO实体 | OO实体 | 标注 |
| 服务契约 | 接口 | 使用[ServiceContract]]标注接口 |
| 服务操作 | 方法 | 使用[OperationContract]标注接口方法 |
| 实现类 | 类 | 使用[ServiceBehavior]标注类,它由服务契约接口派生。 |
| 实现方法 | 方法 | 使用[OperationBehavior] |
| 数据契约 | 类 | 使用[DataContract]标注类,[DataMember]标注成员 |
表1 WCF中的SO实体和OO实体的关系。
表1显示了SO实体与OO概念之间的映射(由Indigo编程模型定义),以及将它们关联起来的标注6。SO与OO的融合既是Indigo的主要优点,也是它的缺点:
Indigo支持2种主要的服务调用方式:
根据服务提供的访问类型(RPC vs. 消息传递),它的契约被定义成接口(RPC)或消息(消息传递)契约形式(参见表1)。
Indigo的另一个基本特性是:引入连接器(提供安全可靠的通信的托管框架)用于访问服务端点。通过将“管道部分”分离进入单独的类(类层次),并在大多数情况下提供“标准”实现,连接器减少了用于构建互操作服务所必须的“管道代码(plumbing code)”,从而简化了“被连接系统”网络的创建7。
Indigo连接器使用很少的概念(端口、消息和信道),使得服务调用独立于传输协议或目标平台。它们中最重要的是信道(channel),它抽象了给(从)端口发送(接收)消息的处理过程。Indigo5中定义了2类信道:
Indigo同样支持组合信道概念——将一个信道置于其他信道之上。如,可以使用将安全协议信道置于HTTP传输信道之上来提供安全的HTTP传输通信。
Indigo连接器提供了一个构建(Build)为中介提供支持,包括防火墙、代理和应用程序级网关。这些中介是成功实现SOA所必须的很多模式的实现基础,包括消息验证、安全性加强、传输层交换、监视和管理、负载均衡和基于上下文的路由。
除了支持业务服务创建,Indigo还提供几个系统服务,它们可以被任何业务服务实现使用。这些服务的例子如下:
Java Community Process利用应用服务器托管应用程序的成功,将它的JBI实现建立在服务容器概念之上。
就像Java业务集成(IEEE互联网计算)8中定义的那样——“JBI是由容器和插件(Plug-in)组成的可插入式架构。这个容器托管使用消息路由进行通信的插件组件。架构上,组件通过一个抽象的服务模型(一个消息传递模型,位于任何特殊协议或消息编码之上的抽象层中)进行交互。"
在基于JBI的实现中,服务之间并不直接交互。取而代之的是,采用类似EAI实现中广泛应用的消息代理架构,JBI容器扮演在服务之间路由消息的通用中介.分离交换的参与者(JBI架构的基础9)在服务提供者和消费者之间提供了解耦,以及一个用于协调(mediating)服务通信量(或插入所有额外需要的功能)的明确位置e。
此时,协调器(Mediation)可以支持广泛的功能,从消息传送和安全加强,到基于内容的路由和服务标本标定。
JBI容器托管了2类不同的插件组件9:
组件间的交互利用了基于WSDL 2.0的标准化服务定义。WSDL 2.0定义在服务消费者和提供者之间提供了共享的协议,并作为JBI实现互操作能力的基础。
除了标准化的服务定义,JBI使用“通用化(normalized)”消息的概念支持全局组件互操作能力。消息通用化将协议与业务特定的上下文映射成一个通用的、可传输风格,这与EAI实现中经常使用的“规范(canonical)”消息表示概念非常类似g。
每个JBI容器存在于一个单独的虚拟机中,并容纳所有的BC和SE,容器提供了一组服务,为SE和BC实现提供操作性支持。
JBI也定义了基于JMX的标准控制集合,允许外部管理工具执行不同的系统管理任务,也可以管理组件本身。管理支持为以下情形提供了标准机制9:
尽管服务组件架构(SCA)10被作为规范定义(该规范定义了使用面向服务架构构建系统的模型),但它是一个有效的模型(该模型用来将组件组合成服务),并为服务组合成解决方案提供了额外支持。
一个组件实现由以下的4组规范定义10:
这个元模型中实例的概念有别于在OO中使用的实例概念。此处的组件实例是指一个带有被完整解析的属性集,为解决特殊问题而修改组件行为的组件实现。
一个组合定义了很多组件实例,它们彼此交互,这里的交互使用连线(wire)来定义。
在SCA中,连线使得绝大多数的底层代码被抽出(与Indigo中的信道类似)。如,连线可以被定义同步的或异步的,支持组件调用的事务行为等。SCA在幕后处理这些底层细节。连线同样可以在任意方向上连接2个不同的接口语言(如Java接口和WSDL 端口类型/接口),只要这2个接口定义的操作是等价的就行了。
除了连线,SCA也支持通过特殊的组件类型,如导入(imports)和导出(exports),进行模块间通信。连线、导入和导出组件的结合使得组件可以引用外部服务。
组合元模型定义的组件组合,与服务组合既类似又不同,尽管两者都定义了使组件/服务一起工作的方式。通过被组合本身引入的功能,服务组合增强了参与服务的功能;而这个元模型只定义组件(更接近于服务实现)间的连接。
SCA实现依赖于服务数据对象(Service Data Objects,SDO)10,它提供了表示数据的通用模型的技术。SDO是组件的数据交换基础。SDO架构中的基本概念是数据对象——包含基本类型数据和(或)其它数据对象的容器。元数据提供了被包含数据的信息,它被数据对象显式引用。在SDO中数据对象的组合由数据图表示。除了对象本身,图中还包含变更概要,用来记录图中数据对象和属性在处理过程中变化的信息(类似微软环境中的ADO)。除了SDO,SCA还引入了服务消息对象(Service message objects,SMO),它提供了服务间处理和交换消息的抽象层(类似JBI中的标准化消息)。
SCA目前尚显稚嫩(本文写作时版本为0.9),并且还不支持SOA实现要求的大多数模式。作为替代,目前IBM的Websphere ESB/WPS 6.0的SCA实现引入了协调器框架12 ,它基于SCA并为协调器实现和定位提供了定义良好的机制。(类似Indigo中的中介)。
如果GUI支持,SCA实现会非常强大,可以在面板上实现图形化组件的连接,这种方式正是IBM的WebSphere Integration developer(WID)13 14 中所实现的。
| SDO API 包括一个动态数据API,一个数据自检API,和一个数据跟踪API.
SDO基于“数据对象”的概念,“数据对象(DataObject)”简单的说就是包含某个数据的一个对象的实例, 通常,程序员使用传统的Java对象(POJO,或JavaBean)或是传统的Java接口对象(POJI)来以一种持久性机制 中立的风格表示数据(不久将更多利用于关系型和XML数据上)。举例来说,程序员为了使用POJO普遍会构造“数据传输对象” 。我们称“Java Bean”类型API为“静态的”,因为预先定义好的具有一系列属性(getter/setter方法)的数据类型已经存在了。 然而,静态数据API并不总是执行,因为有时Java类甚至还不一定存在。举例来说,在许多动态查询中,返回的数据形式并不是 已知的预先类型,这样我们就不能将数据填写到已存在Java类中。另一例子是,数据结构是可扩展的;例如,对于XML数据, 在您剖析它之前,通常不知道它的精确类型(假定它的XML模式结构是可扩展的)。 这就是SDO数据对象接口的便利之处:它提供了“动态的”数据API,当您需要产生一个能支持包括动态查询、未知数 据类型和可扩展模式等情况的通用框架,有一个动态数据API会更加有用。 DataObject上基本操作是set([property name],[property value])和get([property name])。在DataObject 上有更多的方法,下面就让我们了解它们。假定我们有这样一个接口。如下:
模拟的客户代码如下(假定实现Persion接口的一个实现为PersionImpl JavaBean存在):
上面的是Java程序员中许多程序设计中使用的。但是,如果在运行时我要处理persion数据的时候,persion接口确不存在, 那会怎么办呢,这是我们就能使用DataObject,假定有一个DataObject的实现DataObjectImpl。它有一个默认的构造 函数(注意,SDO规范的内核只定义接口),我可以写出以下代码,它同上面的代码可以完成同样的事情。
这样,客户也不能做任何运行是的类型检查。SDO处理的这个问题,下面我们就来讨论它。Java对DataObject的需求增加 是有意义的。因为Java是一种静态类型的语言,它不能在运行时将额外的字段和方法添加到对象的实例中去。也不是所的语言 都象这样。 DataObject不只提供了get()和set()这两种简单获取和返回java.lang.Object的方法。在传统的POJO或POJI中,访问程序 要指定更加确定的类型。也就是,它们处理String、int、calendar等,而不是对象。DataObject接口允许它的属性也被赋 预类型,并且为此提供了附加的getter和setter。这与java.lang.reflect.Feild提供的getter和setter相似。例如,在对象 的例子中,我可以按如下来做:
当然在这里更改以上代码中的最后一行并非是必须。但如果需要作为一个字符串在返回的对象上操作,则需要显示的getString(); Java的其他动态数据API 在出现其他的DataObject之前,Java还有其他的动态API。主要地讲,JDBC ResultSet和ResultSet API是用于关系数据的动 态数据API,而DOM API(尤其是结点和元素)是用于XML数据的动态数据API,使用这些API的对等代码大致如下(为了简单起见, 显示get和忽略set ):
这里的突出点在于,SDO的DataObject接口是一个泛化的动态数据API,这意味着它可以独立于任何特定的持久性机制或 串行化格式而被使用。人们将它设计得可良好处理对象数据、关系数据、列表数据与XML数据。它允许更高级别框架处理来 自多个异构数据源的数据。 类型和特性 POJO和POJI等静态类型的数据API将所有的类型信息硬编码到基中。接口或类定义了类型,而且这一类型具有用静态类型 的getter与setter访问的特性。同是,这些类型可以用java.lang.Class与java.lang.reflect API来自省。这些可以用于 多个东西,从简单的运行时类型测试到使泛化框架在您的Java对象上操作。在Java类与接口不存在的情况下,很显然不能 采用这种方式。我们在SDO需要一等同的与java.lang.Class和java.lang.reflect.Field的东西。这正是类型和特性接口 所扮演的角色。类型大约等同与类,而属性大约等同于字段。 让我们看一段代码。在接口Persion存在情况下,我们可以如下利用类型信息:
使用SDO API,则可以如下编写代码:
注意,为了上面的代码正确工作,类型信息必须来自某个地方,您将注意到,在上面的代码中,我假设有一个简单的未用 任何参数构造的DataObjectImpl对象--如果你想创建一个带有一个类型的DataObject,就需要改变这种状况。可能 有人会问:为什么SDO要定义具体的类来从零构建SDO。这可在最后来完成。我们首先将重点放在提供一个可以消费SDO 的客户端API上,同是假定支持SDO的产品暂时将以一种专有的方式来构造SDO。这将随着时间的推移而随时更改。除了 询问DataObject的类型外,还可以询问它的Property对象集。这使得各个工具可以遍历DataObject的图。下面就是 这样的一个工具,功能是打印出一个DataObject的属性:
Java bean和SDO联姻 表示数据的预定义POJO和POJI比DataObject接口更易于共用。如前面所指出的,这并不总是可能的。如果我需要编写 一个能够处理最小公分母的框架,该框架应该能够和DataObject共用。但我们并不希望将我们的Java bean用户晾在一边。 那么我们能做些什么呢?这里有一些可行的策略。 让我们拿JAXB做例子。一个兼容JAXB的工具可以从XML 模式定义(XSD)生成POJI,而这个工具还将生成“Impl” 类来实现这些接口。一个人可以设想一个JAXB 模式编译器是支持SDO的,Impl类也由此而实现DataObject接口。因此, 这些框架可以带有一个JAXB生成的对象并成功地向下转型(downcast)到DataObject。 变更跟踪 SDO有很好的记忆能力:它们可以记住过去发生了什么,并告诉您什么发生了变化。这一点为何很有用呢?一个非常常见 的访问模式是:一个客户端(如一个Web应用程序)接收到来自一个数据源的信息,更改该信息的一部分,然后使数据源 提交这些更改。在SOD架构中,我们将负责答复查询和提交更改的服务称为一个“中介”(mediator)。这个中介将一个 数据源做“前端”来完成上述任务。因此,您可以具有SQL/关系中介、命中XML数据仓库的XML查询中介及其所有种类的 组合。为了使中介完成其将更改提交给一个DataObject的任务,它需要能询问DataObject什么已经被更改。 DataGraph界面提供了一个方便的机制来传递一组数据。DataGraph接口提供了getChangeSummary()方法,它退还一 个ChangeSummary对象。从这个对象中,您可以得到一个已被更改的数据对象和哪些是新值的列表。还有一种额外的方法 getOldValues()可告诉您一个DataObject的旧值是什么。 |
| 原文链接: http://www.codefutures.com/weblog/andygrove/archives/2006/03/sdo_versus_dao.html 前不久总有人问我SDO和DAO之间的区别,我当时无法给出一个简短的回答,所以我决定把那些小文章汇总到这里,为以后参考之用。 我觉得开始最好分别听听DAO和SDO的作者是怎么描述各自的东东的。 摘自《Core J2EE Design Patterns - Java Blueprints》网站: “Data Access Object (or DAO) 模式: ×将一个数据源的客户端接口与数据访问机制分离 ×将一个特定的数据源访问接口适配成一个通用的客户端接口(译者按:Java中就是JDBC啦 )DAO模式使得数据访问机制可以独立于访问数据的代码进行变动。 ” 在SDO规范中则写有这么一段话: “Service Data Objects (SDO)是一种数据编程架构和一组API。 SDO主要用于简化数据编程,让开发人员能集中解决业务逻辑问题而不是底层技术(译者按:每个规范中似乎都有这么一套说辞,类似于十六中全会 )SDO通过以下手段简化数据编程: ×统一不同类型的数据源的数据访问编程 ×提供一套一致的应用模式的支持 ×让应用、工具和框架能够更便捷地查询、浏览、绑定、更新和获取数据的元信息。” 很显然,DAO和SDO的目标有很多共同点. 最值得注意的一点就是: ×SDO和DAO均提供了一套语言级的API将客户端代码从底层数据源API中抽象出来 ×SDO和DAO都可以用在任何数据源上(数据库,XML文档,企业系统,等等) 不过,它们之间也有一些显著的差异: ×DAO是一种设计模式,而SDO是一个规范。这是一个相当大的差异。由于SDO是一个规范,开发商可以开发于标准兼容的工具、驱动或框架。这意味着开发者不用在项目一开始就从头开始手工设计和编写DAO对象的代码,而是利用已有的SDO工具和框架以大大减少开发的时间和费用。需要一提的是,虽然有FireStorm/DAO这样的DAO框架,但由于DAO的实现不是标准化的也没有相应的规范,所以一些开发者不是甚喜欢这类工具。 ×SDO提供了脱机模式的访问,data graph(树状结构的数据对象的集合)可以脱离数据源离线修改,轻易地在分布式服务间传递(以Java对象或XML文档的方式),之后再发回到数据访问服务层并持久化到数据源中。DAO设计模式则没有相关的要求 ×SDO 既提供了动态API,也规定了如果通过数据源的schema来生成静态API的代码(译者按:即POJO和getter/setter方法生成)。这使得用户可以在动态和静态API访问方式间选择,并且可以在一个应用中同时使用两种方式!DAO则没有提供动态API,这样一来为了动态访问数据,开发人员不得不退回到使用类似JDBC的这样的低级API。 ×SDO 提供了一套SDO的数据类型来保证不同类型的数据源和不同语言之间的可移植性和兼容性。现在SDO已经有了Java, C++, 和 PHP上的实现. DAO则是Java标准,并没有涉及类似的话题 ×SDO 特别适合与基于Service Oriented Architecture (SOA) 架构的设计模式。SDO规范的最新版本已经和SCA规范一起发布了。SCA实现了分布式SOA架构下服务之间的点到点互动。SCA是业界对微软的 Indigo/WCF 战略的强有力的回应,也许是这两年 SOA/Web Services 上最重要的发展。 剩下的问题显然是何时使用DAO,何时使用SDO. DAO对于将客户端代码从各种类似JDBC, EJB CMP, 或 Hibernate等持久化技术中抽象出来是一种很不错的选择, 它让应用中的数据访问代码与底层的持久化技术(有可能被要求替换)互相隔离,同时简化了应用的部署。当DAO代码可以使用FireStorm/DAO这样的工具来生成的时候,开发时间被大大减少了。 对于用于面向服务架构下的应用、多语言环境或需要以脱机方式访问数据的情况,使用SDO开发应用则是个很不错的选择。 |