内容


使用 Spring Framework 设计和开发 SCA 组件,第 1 部分

三剑客:Spring、SCA 和 Apache Tuscany

Comments

系列内容:

此内容是该系列 # 部分中的第 # 部分: 使用 Spring Framework 设计和开发 SCA 组件,第 1 部分

敬请期待该系列的后续内容。

此内容是该系列的一部分:使用 Spring Framework 设计和开发 SCA 组件,第 1 部分

敬请期待该系列的后续内容。

简介

在 Open SOA (OSOA) 项目发布标题为 “强大的组合:SCA、OSGi 和 Spring” 的白皮书之后,这三种技术的结合引起了人们的一些关注。Spring Dynamic Module 就是这种基础架构的一种商业实现,它结合了 Spring 和 OGSi。Spring beans 可以作为服务组件架构(SCA)的组件实现使用。Apache Tuscany 的 Java 实现建立在 Apache 的 OSGi 框架 (Felix) 的基础之上。

在本系列中,学习如何使用 Spring Framework 和 Apache Tuscany SCA Java 运行时来设计和开发 SCA 组件。示例和代码片段将帮助您理解 SCA 与 Spring 两者结合所带来的好处。您还将了解如何结合 SCA 与 Spring 来创建分布式服务应用程序。

本文将介绍使用 Spring 开发 SCA 组件时需要掌握的一些基本设计原则。您将探索如何将 Spring beans 公开为 SCA 服务,以及如何在 Spring 应用程序中访问 SCA 服务和属性。

第 2 部分将深入讨论一些高级特性,比如说通过 SCA 处理多种应用程序上下文以及在 Spring beans 中使用 SCA 注释。

下载 示例源代码。此示例需要在 Apache Tuscany 运行时中运行,但其侧重点并不是展示如何开发 SCA 组件。本文将重点讨论如何将 Spring 应用程序作为 SCA 组件的一种实现技术来使用。

程序

本文将讨论以下程序。

SCA
提供了一个编程模型,用于创建基于面向服务架构(Service-Oriented Architecture ,SOA)的应用程序和解决方案。SCA 所依托的理念是将业务功能作为一系列服务提供,从而创建能满足特定业务需求的解决方案。这些复合集可以包含为已有系统中的应用程序和业务功能创建的新服务,以及作为复合应用的一部分重用的应用程序。SCA 提供了:
  • 一个用于服务复合以及服务组件创建的模型,包括在 SCA 复合集中重用已有应用程序。
  • 灵活的复合、重用、技术和部署选择,这使它成为了构建异构分布式系统的理想环境。
  • 支持多种实现语言和通信机制。
  • 简化的组件编程模型,用于使用各种技术(比如说 Enterprise JavaBeans、Java POJOs、Spring beans、BPEL Process、COBOL、C++ 和 PHP 等)来实现业务服务。
Spring Framework
通常称作 Spring,它是一个尝试通过解决企业应用程序开发的复杂性来提高 J2EE 环境适用性的开源项目。Spring 的一个优势在于它的分层架构。它允许您选择所使用的组件,同时为 J2EE 应用程序开发提供了一个紧密结合的框架。Spring 为简单的 Java 对象提供了一个框架,从而使它们能够通过包装器类和 XML 配置来使用 J2EE 容器。Spring 的目标是,通过提高开发生产力和运行时性能,让项目从中获得巨大的好处,并改善测试范围和应用程序质量。人们经常将 Spring 描述为一种轻量级的容器环境,但更加恰当的比喻或许是 “能简化开发的框架“。
Apache Tuscany
开源 Apache Tuscany 项目致力于实现 SCA 规范(和一些其他的 SCA 规范,如 Service Data Objects 和 Data Access Service)。依照 Open Service-Oriented Architecture (OSOA) 和针对全球信息社会 (OASIS SCA Java) 规范的一些标准,Apache Tuscany 为 SCA 运行时提供了一个全面的基础架构。本文中的示例将使用 Apache Tuscany V1.5,它是截止本文撰写时的最新版本。要运行示例应用程序,需要 下载 Apache Tuscany SCA Java 实现的二进制发行版。

SCA Assembly Model

SCA 的基本工件是组件,它是 SCA 的基本构成单元。组件包含一个经过配置的实现实例,其中,实现是提供业务功能的程序代码。业务功能将由其他组件作为服务提供。实现有时需要依赖于其他组件提供的服务。这些依赖关系被称作 引用

实现具有可设置的 属性,它们是影响业务功能运转的数据值。组件通过为属性提供值以及将引用关联到其他组件所提供的服务来配置实现。多个组件可以使用和配置同一实现,而每个组件可以采用不同的方式来配置实现。

SCA 支持:

  • 各种实现技术,比如说 Java POJOs、EJBs、Spring beans、BPEL Process、COBOL 和 C++
  • 一些脚本语言,比如说 PHP 和 JavaScript
  • 一些声明式语言,比如说 XQuery 和 SQL

SCA 在一种被称作复合集(composites) 的集合中描述应用程序的内容和关联,如图 1 所示。复合集可以包含组件、服务、引用、属性声明以及这些元素之间的关联描述。复合集可以分组和链接采用不同实现技术构建的组件,从而允许在各业务任务中采用适当的技术。复合集将部署在 SCA 域中。

图 1. SCA 复合图
SCA 复合图
SCA 复合图

SCA Assembly Model 包含一系列工件,它们在复合集方面定义了 SCA 域的配置,其中包括服务组件以及描述组件之间的关联的相关工件。有关 SCA Assembly Model Specification 的更多详细信息,请参阅 参考资料

SCA 与 Spring 两者相结合的优势

Spring Framework 与 SCA 采用许多相同的设计原则。SCA 将 Spring 视为其组件的一种实现技术。SCA Spring Component Implementation Specification 定义了如何采用这种方式来使用 Spring。

与 Spring bean 类似,SCA 组件可以包含到其他组件所提供的服务的引用,并且有一些属性可供配置。与 Spring 形成对比的是,SCA 是一种跨语言的分布式组件架构,它支持多种组件通信机制。通过将 Spring beans 发布为可由其他组件访问的服务并为 Spring beans 提供关联到其他(可能为远程)组件的服务的引用,SCA 可以扩展 Spring 组件的功能。

要将 SCA 与 Spring 相结合,一种有效的方法是使用 Spring 来构建 “粗粒度” 的服务组件实现,并引入到 SCA 中以便公开服务、关联服务组件以及处理异构和分布式系统。SCA 可以在使用 Spring 实现的应用程序中添加一些有用的功能,比如说:

  • 对远程组件以及多种协议的扩展支持
  • 支持使用不受 JVM 支持的各种编程语言来编写组件
  • 支持 WS-Policy 针对安全性和事务等活动指定的策略

易于测试组件是 Spring 的一项优异的特性。缺少 API 和注入技术导致您只能使用简单的模拟对象进行测试。SCA 在服务方面对此进行了补充,因为关于服务组件的 SCA 复合集可以方便地切换到模拟配置以进行测试。

将 Spring 应用程序定义为 SCA 组件

在 Apache Tuscany SCA 实现中,SCA 使用 Spring 作为其组件在 SCA 复合集中的实现技术。可以将 Spring 应用程序定义为 SCA 复合集中的 SCA 组件,即 SCDL,其格式如下所示。

清单 1. 包含一个 Spring 组件的 SCA 复合集
<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
      xmlns:tuscany="http://tuscany.apache.org/xmlns/sca/1.0"
      targetNamespace="http://calc"
      xmlns:c="http://calc"
      name="Calculator">

    <component name="CalculatorServiceComponent">
             <implementation.spring location="targetURI"/>
    </component>

</composite>

<implementation.spring> 元素的位置属性可以指定目标 URI 指向某个存档文件 (.jar) 目标,或者 直接指向 Spring 应用程序上下文。

以下列表给出了指定 <implementation.spring> 位置属性的目标 URI 的可能方法。

指定 Spring 应用程序上下文文件
<implementation.spring location="application-context.xml"/>
指定目录
<implementation.spring location="./spring"/>

目标 URI 将资源指定为名称为 spring 的目录,其中包含所有与 Spring 相关的文件。META-INF/MANIFEST.MF 文件必须包含在 Spring 目录中,它使用 Spring-Context ::= <path> 格式的 Spring-Context 头部指定到上下文配置的路径。其中,path 相对于 Spring 目录。如果 MANIFEST 文件中没有 MANIFEST.MF 文件或 Spring-Context 头部,则默认行为是使用 Spring 目录下的 META-INF/spring 目录中的 application-context.xml 文件建立应用程序上下文。
指定存档文件
<implementation.spring location="spring.jar"/>

目标 URI 将资源指定为 spring.jar 存档文件,其中包含与 Spring 相关的所有文件。META-INF/MANIFEST.MF 文件必须位于 spring.jar 存档文件中,它使用 Spring-Context ::= <path>. 格式的 Spring-Context 头部指定到上下文配置文件的路径。其中,path 指向 spring.jar 存档中的文件。如果 MANIFEST 文件中没有 MANIFEST.MF 文件或 Spring-Context 头部,则默认行为是使用目录 spring.jar 存档文件中 META-INF/spring 目录下的 application-context.xml 文件建立应用程序上下文。

基于 Spring 的 SCA 组件

组件实现的业务功能将由其他组件作为服务 提供。实现可以依赖其他组件提供的服务;这些依赖关系被称作引用。实现可以有可设置的属性,即影响业务功能运转的数据值。下面的例子展示了如何将 Spring beans 提供为 SCA 服务,以及如何在您的 Spring 应用程序上下文中配置 SCA 引用和 SCA 属性。

示例

我们以图 2 中的 CalculatorComponent 为例。它需要依赖其他组件(AddComponentSubtractComponentMultiplyComponentDivideComponent)来实现所需的功能。在本例中,CalculatorComponent 的业务功能是使用 Spring beans 实现的,AddComponent 是使用 JavaScript 实现的,SubtractComponentMultiplyComponent 是使用简单 POJO 实现的,而 DivideComponent 是使用 Groovy 脚本实现的。

图 2. 基于 Spring 的 CalculatorComponent
基于 Spring 的计算器组件
基于 Spring 的计算器组件

下一步是创建一个名称为 calculator.composite 的 SCA 复合集(如清单 2 所示)来定义组件、服务、引用、属性声明以及这些元素之间的关联描述。详细信息请参见 下载 小节。

清单 2. calculator.composite
<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
      xmlns:t="http://tuscany.apache.org/xmlns/sca/1.0"
      targetNamespace="http://calc"
      xmlns:c="http://calc"
      name="Calculator">

    <component name="CalculatorComponent">
        <implementation.spring location="META-INF/spring/calculator-context.xml"/>
        <service name="CalculatorService">
            <interface.java interface="calculator.CalculatorService"/>
            <t:binding.rmi host="localhost" port="8099"
                        serviceName="CalculatorRMIService"/>
        </service>
        <reference name="addService" target="AddComponent" />
        <reference name="subtractService" target="SubtractComponent" />
        <reference name="multiplyService" target="MultiplyComponent"/>
        <reference name="divideService" target="DivideComponent" />
    </component>

    <component name="AddComponent">
        <t:implementation.script script="calculator/AddServiceImpl.js"/>
    </component>

    <component name="SubtractComponent">
        <implementation.java class="calculator.SubtractServiceImpl"/>
    </component>

    <component name="MultiplyComponent">
        <implementation.java class="calculator.MultiplyServiceImpl"/>        
    </component>

    <component name="DivideComponent">
        <t:implementation.script script="calculator/DivideServiceImpl.groovy"/>
    </component>

</composite>

calculator.composite 使用 <reference> 元素定义 CalculatorComponent 与其他四个服务之间的依赖关系,比如说 AddComponentSubtractComponentMultiplyComponentDivideComponent。它们是使用不同技术实现的。AddComponent 提供 addService 实现,用于返回两数之和。同样,SubtractComponent 提供 subtractService 实现,用于返回两数之差。MultiplyComponent 提供 multiplyService 实现,用于返回两数之积。DivideComponent 则提供 divideService 实现。

您可能注意到在 calculator.composite 中,AddComponentSubtractComponentMultiplyComponentDivideComponent 并未使用 <service> 元素明确公开任何服务(采用这种方式,本示例声明为 CalculatorComponent 公开了 CalculatorService)。这样,当您的 SCA 组件未使用 <service> 元素明确公开任何服务时,则 SCA 运行时默认会使用 binding.sca 绑定公开您的组件。同样,在 CalculatorComponent 中,您不必为这些组件引用指定任何具体的绑定信息。SCA 运行时提供了默认的 binding.sca 绑定,用于关联各组件。有关 binding.sca 的详细信息,请参阅 SCA Assembly Model Specification。

在本例中,CalculatorComponent 是一个 Spring 应用程序,它使用 Spring beans 定义了业务逻辑。在您的 Spring 应用程序上下文定义文件中声明所需的 SCA 依赖关系非常重要。

创建一个名称为 calculator-context.xml 的 Spring 应用程序上下文定义文件。如清单 3 所示,通过声明实现所需功能需要的 beans 以及它们的依赖关系,提供了 CalculatorComponent 的业务逻辑。

清单 3. calculator-context.xml
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:sca="http://www.springframework.org/schema/sca"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/sca 
       http://www.osoa.org/xmlns/sca/1.0/spring-sca.xsd">

    <bean id="Calculator" class="calculator.CalculatorServiceImpl">        
        <property name="add" ref="addService"/>
        <property name="subtract" ref="subtractService"/>
        <property name="multiply" ref="multiplyService"/>
        <property name="divide" ref="divideService"/>
    </bean>

</beans>

在 calculator-context.xml 中,calculator bean 通过将所需的依赖关系设置为属性定义了 CalculatorComponent 的业务逻辑。对于 Spring bean 来说,每个属性都是对要设置的值的实际定义,或容器中另一个 bean 的引用。在本例中,calculator bean 依赖于复合集中的组件所提供的各种 SCA 服务,因此应该将属性设置为引用(设置 ref 属性的值)calculator.composite 中定义的 SCA 引用。由于目标是将 CalculatorComponent 公开为服务,因此还应声明需要为 calculator.composite 中定义的 SCA 服务公开哪些 bean。

Spring 组件实现规范和 Apache Tuscany SCA 运行时允许您将 SCA 引用和属性声明为 bean 属性。您还可以声明被显式或隐式地公开为 SCA 服务的 bean,如下所述。

声明显式 SCA 服务、引用和属性

SCA Spring Component Implementation Specification 和 Apache Tuscany SCA 运行时允许您使用 Spring SCA 模式中的自定义 SCA 名称空间元素在 Spring 应用程序上下文文件中声明 SCA 服务、引用和属性。您可以使用自定义 SCA 名称空间元素将 Spring beans 声明为 SCA 服务,并通过 SCA 组件定义指定到所获取的 SCA 服务和属性的引用。使用 Spring 应用程序上下文文件中的 SCA 名称空间元素被称作 SCA 服务、引用和属性的显式声明

用于在应用程序上下文文件中声明 SCA 服务、引用和属性的自定义 SCA 名称空间将在下面详细讨论。

<sca:service>
允许您控制需要将哪些 Spring bean 公开为 SCA 服务。为您提供一种方式来控制将哪些 Spring bean 公开为 SCA 服务。SCA 运行时负责创建合适的服务器绑定,根据 SCDL 配置将需要的策略应用到这些服务上。
<sca:reference>
为您提供一种方式来声明 Spring 应用程序上下文对复合集中的其他 SCA 组件所提供的服务的依赖关系。该 SCA 运行时负责创建合适的引用绑定,根据 SCDL 配置将需要的策略应用到这些服务上。
<sca:property>
为您提供一种方式来声明 Spring 应用程序上下文对由 SCA 组件实现提供的可设置属性的依赖关系。<sca:property> 元素的 name 属性应该在复合集中拥有一个与所含组件相匹配的 SCA 属性。

在 calculator-context.xml(在 清单 3)中使用自定义名称空间元素声明 SCA 服务、引用和属性,如下所示。

清单 4. calculator-context.xml
<beans xmlns="http://www.springf
ramework.org/schema/beans"
       xmlns:xsi="http://www.w3.org
       /2001/XMLSchema-instance"
       xmlns:sca="http://www.springframework.org/schema/sca"
       xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/scahttp://www.osoa.org/xmlns/sca/1.0/spring-sca.xsd"
> <sca:service 
name="CalculatorService" type="calculator.CalculatorService" target="Calculator"/>

    <bean id="Calculator" class="calculator.
    CalculatorServiceImpl">        
        <property name=
        "add" ref="addService"/>
        <property name=
        "subtract" ref="subtractService"/>
        <property name=
        "multiply" ref="multiplyService"/>
        <property name=
        "divide" ref=
        "divideService"/>
    </bean> 
    <sca:reference name=
    "addService" type=
    "calculator.AddService"/>    
    <sca:reference name=
    "subtractService" type="calculator.SubtractService"/>    
    <sca:reference name=
    "multiplyService" type="calculator.MultiplyService"/>    
    <sca:reference name=
    "divideService" type=
    "calculator.DivideService"/> 
</beans>

如清单 4 所示,<sca:service> 元素声明提供 CalculatorService 作为来自目标 calculator bean 的 SCA 服务。必需的 name 属性拥有的值应该与在 calculator.composite 中为 CalculatorComponent 定义的 <service> 元素的名称相同。必需的 type 属性应该将服务类型声明为一个 Java 类的完全限定名。必需的 target 属性应该拥有应用程序上下文中的一个 <bean/> 元素的名称,该元素提供由此 <sca:service> 元素声明的服务。

清单 4 中的 <sca:reference> 元素声明此应用程序上下文对由复合集中其他可用的 SCA 组件提供的服务的依赖关系。在本示例中,calculator bean 依赖于 SCA 服务,比如 AddComponentSubtractComponentMultiplyComponentDivideComponent。这些依赖关系使用 <sca:reference> 元素进行声明。此元素的必需 name 属性拥有的值应该与在 calculator.composite 中为 CalculatorComponent 定义的 <reference> 元素的名称相同。必需的 type 属性应该将服务的类型声明为一个 Java 类的完全限定名。对于 calculator.composite 的 CalculatorComponent 中的每个 <reference> 元素,会在 Spring 应用程序上下文中声明一个等效的 <sca:reference> 元素。

类似地,<sca:property> 元素允许您声明此应用程序上下文对 calculator.composite 中的 CalculatorComponent 提供的 SCA 属性的依赖关系。必需的 name 属性拥有的值应该与 calculator.composite 中为 CalculatorComponent 定义的 <property/> 元素名称相同(如 清单 2 中所示)。必需的 type 属性应该将属性类型声明为一个 Java 类的完全限定名。

声明隐式的 SCA 服务、引用和属性

SCA Spring Component Implementation Specification 和 Apache Tuscany SCA 运行时支持直接在 Spring 应用程序上下文文件中声明 SCA 服务、引用和属性,无需使用在 Spring SCA 模式中定义的任何自定义 SCA 名称空间元素。在 Spring 应用程序上下文文件中直接使用 SCA 引用和属性(无需自定义 SCA 名称空间)称为 SCA 服务、引用和属性的隐式声明清单 3 中的 calculator-context.xml 是一个例子。

在 calculator.composite 文件中定义的具有 addServicesubtractServicemultiplyServicedivideService 等名称的 SCA 引用(参见 清单 2)可以直接用作 Spring 应用程序上下文中的 bean 引用(如 清单 3 所示)。calculator bean 属性可以设置为使用 SCA 引用名直接引用(设置 ref 属性的值)在 calculator.composite 中定义的 SCA 引用(清单 2)。在这种情况下,bean 引用的类型将由 Tuscany 运行时从 bean 类定义中进行内省(introspect),以验证它并将它与在复合集中定义的 SCA 应用类型相匹配。

类似地,在 SCA 复合集中定义的 SCA 属性可以直接用作 Spring 应用程序上下文中的 bean 引用。将 bean 属性设置(设置 ref 属性的值)为使用 SCA 属性名称引用在 calculator.composite 中定义的 SCA 属性。

当应用程序上下文中没有显式的 <sca:service> 元素时,所有顶级的 bean 都将被公开为 SCA 服务,使用 bean 名称作为服务名称。任何内部 bean 或抽象 bean 都不会被用于隐式服务创建。当 Spring bean 实现类实现多个接口时,这些 bean 可以被公开为单个或多个服务。您使用显式的 <sca:service> 元素,其中每个 <sca:service> 元素引用相同的 <bean> 元素,但 type 属性仅使用由 bean 提供的接口之一。在隐式创建服务时,bean 被公开为单一服务,方法是将 bean 类本身声明为服务的一个接口。

尽管 Apache Tuscany SCA 运行时支持使用隐式 SCA 服务、引用和属性,但也有一些场景不适合使用隐式声明。

场景 1. 为集合使用隐式 SCA 引用和属性

在 Spring 中,<list/><set/><map/><props/> 元素允许分别定义和设置 Java Collection 类型 ListSetMapProperties 的属性和参数。清单 5 中的示例 bean 定义演示了在 Spring 的 <list/><set/><map/> 元素中使用隐式 SCA 引用和属性的局限性。

清单 5. 集合的隐式 SCA 引用
<bean id="moreComplexObject" class="example.ComplexObject"> 
  <!-- results in a setSomeList(java.util.List) call --> 
  <property name="someList"> 
    <list> 
        <value>a list element followed by a reference</value> 
        <ref bean="mySCAReference1" /> 
    </list> 
  </property> 
  <!-- results in a setSomeMap(java.util.Map) call --> 
  <property name="someMap"> 
    <map> 
        <entry> 
            <key> 
                <value>an entry</value> 
            </key> 
            <value>just some string</value> 
        </entry> 
        <entry> 
            <key> 
                <value>a ref</value> 
            </key> 
            <ref bean="mySCAReference2" /> 
        </entry> 
    </map> 
  </property> 
  <!-- results in a setSomeSet(java.util.Set) call --> 
  <property name="someSet"> 
    <set> 
        <value>just some string</value> 
        <ref bean="mySCAReference3" /> 
    </set> 
  </property> 
</bean>

假设名为 someList 的 bean 属性的 bean 实现被定义为清单 6 的内容。List 被声明为泛型,以接收其集合中任何类型的 Java 类。

清单 6. someList 属性的 bean 实现
private 
List<?> someList;
    
public List<?> getSomeList() {
    return someList;
}
    
publicvoid setSomeList(List<?> someList) {
    this.someList = someList;
}

在此场景中,Apache Tuscany 运行时无法内省此集合所需的 SCA 引用对象的准确类型(类型 mySCAReference1mySCAReference2mySCAReference3)。必需的 SCA 引用注入将失败。当 someMapsomeSet 属性被声明为接受其集合中任何类型的 Java 类时,相同的规则也适用于它们。建议您总是显式地使用 <sca:reference> 元素声明 SCA 引用,并在这类场景中使用必需的 nametype 属性。

场景 2. 为构造函数注入使用隐式 SCA 引用和属性

Spring 中的构造函数注入允许您通过类构造函数注入依赖关系。为了减少潜在的歧义,Spring 建议只要在 bean 实现中定义了多个构造函数,就为 <constructor-arg> 元素适当使用 indextype 属性。

Tuscany 还建议为 <constructor-arg> 元素使用 indextype 属性,为所有构造函数注入场景显式声明相关的 SCA 引用,即使 bean 只有一个构造函数。

例如,假设您想要使用构造函数为 calculator bean 注入必需的依赖关系(必需的 SCA 引用)。您应该像清单 7 所示的那样定义 bean。在 Tuscany 中,不支持为构造函数使用隐式 SCA 引用和属性。

清单 7. 针对 calculator bean 的构造函数注入
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:sca="http://www.springframework.org/schema/sca"
       xsi:schemaLocation="
       http://www.springframework.
       org/schema/beans 
       http://www.springframework.
       org/schema/beans/spring-beans.xsd
       http://www.springframework.
       org/schema/sca       http://www.osoa.org/xmlns
/sca/1.0/spring-sca.xsd">

    <bean id="Calculator" class="calculator.CalculatorServiceImpl">
    	<constructor-arg index="0" type="calculator.AddService" ref="addService"/>
    	<constructor-arg index="1" type="alculator.SubtractService"
                        ref="subtractService"/>
    	<constructor-arg index="2" type="calculator.MultiplyService"
                         ref="multiplyService"/>
    	<constructor-arg index="3" type="calculator.DivideService" ref="divideService"/>
    </bean>
    
    <sca:reference name="addService" type="calculator.AddService"/>
    <sca:reference name="subtractService" type="calculator.SubtractService"/>   
    <sca:reference name="multiplyService" type="calculator.MultiplyService"/>    
    <sca:reference name="divideService" type="calculator.DivideService"/>

</beans>

SCA 运行时中的应用程序上下文创建

在 Spring 中,主要的模块单元是应用程序上下文,它包含一定数量的 bean(由 Spring 应用程序上下文管理的对象)。应用程序上下文可以在一个分层结构中配置,在其中,子应用程序上下文可以看到父应用程序上下文中定义的 bean,但反之则不行。

默认情况下,Spring 容器在创建容器时验证每个 bean 的配置,包括验证 bean 引用是否实际引用了有效的 bean。对于包含对 SCA 引用和属性的引用的 Spring 应用程序上下文,为在 Spring 应用程序上下文中使用的所有 SCA 引用和属性创建有效 bean 是 SCA 运行时的职责。然后,Spring 容器可以验证 bean 并成功加载应用程序上下文。图 3 给出了一个示例。

图 3. 具有父上下文的 SCA 运行时
具有父上下文的 SCA 运行时
具有父上下文的 SCA 运行时

Tuscany 运行时使用 Spring Binary V2.5.5 加载和运行目标应用程序上下文,这些上下文在 <implementation.spring> 元素的 location 属性中指定,而该元素在 calculator.composite 文件中定义(如 清单 2 所示)。在加载目标应用程序上下文之前,Tuscany 运行时尝试:

  • 内省目标应用程序上下文定义文件,确定在 Spring 应用程序上下文中声明的 SCA 服务、引用和属性。
  • 使用合适的 Spring bean,为在目标应用程序上下文中声明的所有 SCA 引用属性创建一个 SCAParentApplicationContext

在上面的示例中,使用合适的 Spring bean 为在 calculator-context.xml 文件中声明的所有 SCA 引用(比如 addServicesubtractServicemultiplyServicedivideService)创建了一个 SCAParentApplicationContext(参见 图 3)。随后,使用 org.springframework.context.support.GenericApplicationContext 创建目标应用程序上下文,将 SCAParentApplicationContext 声明为它的父上下文。

Tuscany 运行时还提供了必要的基础设施来创建合适的服务绑定,根据 SCDL 配置,为使用 Spring bean 实现的这些服务提供必需的策略。

结束语

本文介绍了如何使用基于 Spring 的应用程序设计和开发 SCA 组件。您现在可以使用自定义 SCA 名称空间元素,在 Spring 应用程序上下文中显式声明 SCA 服务、引用和属性,可以在 Spring 应用程序上下文中直接声明 SCA 引用和属性。您了解了 SCA 运行时如何为 SCA 组件创建目标应用程序上下文。借助示例,本文简短介绍了在应用程序上下文中使用隐式 SCA 引用和属性的局限性。

SCA 和 Spring 能够构成一个强大的组合。Spring 提供了基础设施来开发具有更高效率和运行时性能的组件,还改进了测试覆盖率和应用程序质量。SCA 提供了必要的基础设施来组装和建模基于 SOA 的组件,支持组件公开服务,将服务组件连接在一起,以及处理异构的分布式系统。

敬请期待第 2 部分的推出,第 2 部分将介绍一些高级特性,比如使用 SCA 处理多种应用程序上下文,在 Spring bean 中使用 SCA 注释。


下载资源


相关主题


评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Open source, SOA and web services
ArticleID=448105
ArticleTitle=使用 Spring Framework 设计和开发 SCA 组件,第 1 部分: 三剑客:Spring、SCA 和 Apache Tuscany
publish-date=11192009