SCA(Service Component Arichitecture)
效果:实现了业务组件和传输协议的分离,可以处理各种平台组件的集成。
内容:SCA思想的具体实现是SCA标准和SCA的容器环境。
SCA容器实现了将复杂的服务组件集成过程隐藏在容器内部,开发者之需要按照SCA的标准去开发和集成服务,最终部署到SCA的容器里面即可。SCA容器的实现很复杂,有关其容器的组成与架构也是一种商业秘密。
SCA服务组件 -->服务模块 --> 服务子系统-->example1—helloWorld -->example2—调用不同技术组件
1.1 服务组件
服务组件是SCA中的基本组成元素和基本构建单位,也是我们具体实现业务逻辑的地方。我们可以把它看成是构建我们应用的积木。
如上图,分别讲述服务组成的各个部分:
a)、服务(Service),用来让其他组件调用。是一个接口。如果是基于Java的SCA,它就是Java的接口;也可以是WSDL的ProtType接口,目前只有这两种形式。
b)、组件实现(Implementation),实现所创建的服务,对Java来说,就是接口的实现类。
c)、引用(Reference),一个组件可能需要调用其他组件,需要创建于igeqita组件的引用。对Java来说,就是其他组件的Java接口。
d)、属性(Property),对组件实现的一种属性参数注入。
服务组件提供给别的服务调用的入口叫Interface(接口)。而服务组件本身可能也需要调用别的服务,这个调用出口叫Reference(引用)。无论是接口还是引用,其调用规范都是WSDL或Java接口。
1.2 服务模块
SCA的模块是实际上是将SCA组件(做为零件)重新组合集成度更高的组建,从整体看来SCA模块和SCA组件的结构式一致的。从构成组件的“零件”角度看,SCA模块是用了组件作为零部件重新组装为新的组件(模块)。
其实道理也非常简单,下面是SCA模块的基本原理图:
模块从整体上也是个组件。模块是通过SCA的配置文件配置组装形成的,不需要程序的硬编码。
提升(Promote):就是将组件的接口、属性、或引用装配为模块的对应的接口、属性或引用。
连线(Wire):就是在模块内部,组件之间的调用关系。比如组件A的实现调用了组件B,那么组件AB间就存在一个连线。
当组件之间需要调用的时候,由于目前组件(如EJB、WS、JMS)传输协议的多样化,这样在相互的调用的时候,需要将绑定不同的协议去调用。这些绑定信息包括了目标服务或源服务的调用方式,位置信息,调用的方法等。
模块中的服务组件是不能直接被外部Java代码使用的,为了外部的Java代码,比如JSP/Servlet使用模块中的服务组件,WID工具在模块中提供了一个特殊的端点,叫做Standalone Reference。这个端点只有引用(Reference),而没有接口(Interface)。只要把这个端点的引用连接到需要调用的服务组件的接口,外部的Java代码通过这个引用的名称来调用相应的服务组件了
在一个大的项目里面,可能会有很多服务模块,多个服务模块之间如果需要相互调用,那么就可以将多个服务模块通过WS或者JMS等技术绑定在一起,形成服务子系统。
1.4 example-SCA实现的Hello World组件实例
完整SCA组件Hello World实例包含两部分内容:
1、 SCA组件的服务端代码
服务端代码包括三个部分:
服务接口,一个Java的Interface----HelloService.java。
服务实现,HelloService接口的实现类----HelloServiceImpl.java。
SCA的服务组件配置文件:Hello.composite。
HelloService.java
/**
* 服务接口
*
* @author leizhimin 2009-6-2 15:31:49
*/
publicinterface HelloService {
String getHello(Stringusername);
}
HelloServiceImpl.java
package hello;
/**
* 服务实现
*
* @author leizhimin 2009-6-2 15:32:36
*/
publicclass HelloServiceImpl implements HelloService {
public String getHello(String username) {
return"Hello " + username + "! This is aSCA program!";
}
}
Hello.composite
<!-- SCA的服务组件配置文件-->
<compositexmlns="http://www.osoa.org/xmlns/sca/1.0"name="Hello">
<componentname="HelloServiceComponent">
<implementation.javaclass="hello.HelloServiceImpl"/>
<propertyname="username"type="xsd:string"default="World"/>
</component>
</composite>
2、SCA组件的客户端代码
package hello;
/**
* SCA的客户端调用
*
* @author leizhimin 2009-6-2 15:41:41
*/
publicclass HelloSCAClient {
publicstaticvoid main(String[] args) {
SCADomainscaDomain = SCADomain.newInstance("Hello.composite");
HelloServicehelloService =
scaDomain.getService(HelloService.class, "HelloServiceComponent");
Stringmsg = helloService.getHello("vcom");
System.out.println(msg);
scaDomain.close();
}
}
从客户端的调用代码来看,客户端需要知道服务端组件提供了什么服务,实现了什么纯Java接口。而不需要接口后面的实现细节。
从上面的开发过程可以看到,开发SCA组件,客户端和服务端都不需要知道技术细节。
客户端调用其他组件的时候,只通过一个简单的SCADomain实例,直接获取服务的实现实例就可以调用,而负责的调用和实现都交给了SCA运行环境。
1.5 example—调用不同技术服务组件
本文示例展示了一个简单业务应用程序的演变过程。尽管示例 SCA 应用程序在概念上非常简单,但是其实现却相当复杂。计算器应用程序涉及 4 个不同的服务。每个服务通过不同的技术(Java 技术、Web 服务、HTTP、JScript 和 Groovy)实现或访问。
对这个业务服务的惟一要求就是将两个数字相加。发布计算器服务供客户机调用。此计算机被连接到只有一个功能的 add
服务:将两数相加并返回总和(例如
double add(double o1, double o2)
)。假设接口使用 Java 语言指定,并且服务也通过 Java 语言实现。图 3 展示了这个 SCA 集合。
图 3. 计算加法的 SCA 计算器组件

指定了计算器组件和它的实现后,这个组件将引用 add
服务组件及其实现。清单 1 展示了此业务应用程序的 SCA 复合文件。可 下载 该组件及其他组件的源代码。
清单 1. 计算器复合文件
<composite xmlns="http://www.osoa.org/xmlns/sca/1.0" xmlns:sample="http://sample" name="Calculator"> <component name="CalculatorServiceComponent"> <implementation.java class="calculator.CalculatorServiceImpl"/> <reference name="addService" target="AddServiceComponent"/> </component> <component name="AddServiceComponent"> <implementation.java class="calculator.AddServiceImpl"/> </component> </composite>
假设客户需求增长,并且需要一项可以计算减法的新服务。然而,有一种 Web 服务可以将接口指定为 WSDL 文档并且被实现为一个 Java 程序。此 Web 服务可以通过 Web 服务访问绑定进行访问。因此,通过添加一个引用和访问减法服务的组件,就可以轻松地向 SCA 复合文件添加新的需求。
清单 2. 包含新服务的计算器复合文件
<composite xmlns="http://www.osoa.org/xmlns/sca/1.0" xmlns:sample="http://sample" name="Calculator"> <component name="CalculatorServiceComponent"> <implementation.java class="calculator.CalculatorServiceImpl"/> <reference name="addService" target="AddServiceComponent"/> <reference name="subtractService" target="SubtractServiceComponent"/> </component> <component name="AddServiceComponent"> <implementation.java class="calculator.AddServiceImpl"/> </component> <component name="SubtractServiceComponent"> <implementation.java class="calculator.SubtractServiceImpl"/> <service name="SubtractService"> <interface.wsdl interface="http://calculator#wsdl.interface(SubtractService)" /> <binding.ws uri="http://localhost:8080/SubtractServiceComponent"/> </service> </component> </composite>
要实现业务示例的演变,我们需要添加对乘法和除法服务的需求。这些服务可以以 JScript 和 Groovy 实现的形式获得。Tuscany 允许您轻松地将这些服务添加到复合文件中。业?应用程序表示现在应当如图 4 所示。
图 4. 包含 4 个服务的 SCA 计算器

在应用程序的最后一个 SCA 复合文件中,注意添加的 JScript 和 Groovy 组件是对 SCA 规范的特定于 Tuscany 的扩展。因此,一个新的名称空间属性为这些组件引入了特定于 Tuscany 的语法。
清单 3. 包含 4 个服务的计算器复合文件
<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
xmlns:sample="http://sample"
xmlns:tuscany="http://tuscany.apache.org/xmlns/sca/1.0"
name="Calculator">
<component name="CalculatorServiceComponent">
<implementation.java class="calculator.CalculatorServiceImpl"/>
<reference name="addService" target="AddServiceComponent"/>
<reference name="subtractService" target="SubtractServiceComponent"/>
<reference name="multiplyService" target="MultiplyServiceComponent" />
<reference name="divideService" target="DivideServiceComponent" />
</component>
<component name="AddServiceComponent">
<implementation.java class="calculator.AddServiceImpl"/>
</component>
<component name="SubtractServiceComponent">
<implementation.java class="calculator.SubtractServiceImpl"/>
<service name="SubtractService">
<interface.wsdl interface="http://calculator#wsdl.interface(SubtractService)"/>
<binding.ws uri="http://localhost:8080/SubtractServiceComponent"/>
</service>
</component>
<component name="MultiplyServiceComponent">
<tuscany:implementation.script script="calculator/MultiplyServiceImpl.js"/>
</component>
<component name="DivideServiceComponent">
<tuscany:implementation.script script="calculator/DivideServiceImpl.groovy"/>
</component>
</composite>
该场景可以让您做出两项快速修改,并向初始业务应用程序添加三个组件。新的组件将在初始组件的基础上使用不同技术实现和访问。SCA 可以对变化的和不同种类的业务需求做出响应。
运行 SCA 业务应用程序,SCA 运行时(比如 Tuscany)首先需要加载并配置 SCA 复合文件。对各个复合文件工件进行检查,然后使用工厂方法在内存中实例化不同对象。第二步是实例化用来连接组件的运行时连接(runtime wire)
参考:
http://www.ibm.com/developerworks/cn/webservices/ws-sca/#ibm-pcon
http://www.ibm.com/developerworks/cn/opensource/os-apache-tuscany-sca/index.html