递归的装配模型
SCA协会从内外部提出的进一步简化SCA装配模型的建议需求中获取到了许多反馈意见。反馈中非常清楚地阐述了让SCA装配模型完全具有递归性将是进一步简化的关键所在。
“递归性”基本上意味着装配可以嵌入在其他“高层”装配的内部。装配模型的完整递归性将有助于提升装配的复用性。它也在自顶向下的解决方案设计中支持服务实现的后续分解。
在SCA v0.9装配规范中,(module)模块包含在一系列由“原子”组件实现的组件之间。对于由其他装配集实现的组件,在(module)模块装配级别上没有提供支持。
从系统装配级来看,V0.9规范包含由模块实现的组件,但仅仅是用模块组件来命名这些组件。对于在模块装配级别,它们还不存在可扩展的实现类型这个概念。
所以,在SCA 1.0装配规范中,三项工作简化了模型:
1. 只包含不依赖于任何装配层次级别的组件
2. 组件既可以由简单的实现也可以由装配集来实现
3. 不用术语”module”或”system”来命名装配集,而用composite
允许组件可以由简单的实现或构件来实现为更进一步的简化提供了支持。原子实现和构件应该使用相同的技术,并提供相同的可配置方面(比如:服务,引用和属性)的定义方式。可以通过重命名entry point(v0.9规范中的定义)为service(v1.00规范中的定义),external service(v0.9规范中的定义)为reference(v1.00规范中的定义),并允许为构件定义属性。
在v0.9规范中,module装配和system装配集有构建一系列局部装配集的外部装配的概念。在模块级有称为module的片段,系统级有称为subsystem的片段。在最新的模型中,这个都认为是构件使用的另一种形式。通过将包含构件到另外的构件中来使用它,就意味着构件内容的文本信息包含进含有该构件的构件中。以这种方式用于内含其他构件的构件不一定需要实现—他们可以容纳任意元素集,该元素集完成该含有它们的构件所需的工作。
模型变化小结
以下表格通过对比新老模型总结了模型的变化信息。可以非常清晰地看到是如何通过减少概念的数目的方式来让具有递归性的装配模型简化模型的。
新模型实践
在后面我们用Big Bank案例(在我翻译的BigBank案例中)的变种来演示新的装配模型。
开发装配集
该案例的变种就是使用另一个构件替代POJO来实现bigbank.Account构件的AccountDataServiceComponent。下图展示了两个构件的装配图,bigbank.Account和bigbank.Accountdata构件。后者实现了前者的AccountDataServiceComponent。
如下代码片段展示了bigbank.Account构件的定义。它定义了AccountDataServiceComponent,该组件的实现使用了bigbank.Accountdata构件。它还展示了如何为构件定义property,构件属性是如何设置的,这里在AccountServiceComponent上使用了属性。该案例还展示了构件中的entry point现在称为service,external service现在称为reference。组件属性和引用都以XML方式配置的方式也可以剔除v(v在V0.9规范中的命名空间,会引发冲突)的使用简化使用。
<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
xmlns:bb="http://bigbank.com"
targetNamespace="http://bigbank.com"
name="bigbank.account">
<service name="accountService" promote="AccountServiceComponent">
<interface.java interface="services.account.AccountService"/>
<binding.ws port="... #wsdl.endpoint(AccountService/AccountServiceSOAP)"/>
</service>
<property name="currency" type="xsd:string">USD</property>
<component name="AccountServiceComponent">
<implementation.java class="services.account.AccountServiceImpl" />
<property name="currency" source="$currency"/>
<reference name="accountDataService" target="AccountDataServiceComponent"/>
<reference name="stockQuoteService" target="StockQuoteService"/>
</component>
<component name="AccountDataServiceComponent">
<implementation.composite name="bb:bigbank.AccountData"/>
</component>
<reference name="StockQuoteService"
promote="AccountServiceComponent/stockQuoteService">
<interface.java interface="services.stockquote.StockQuoteService"/>
<binding.ws port="...#wsdl.endpoint(StockQuoteService/StockQuoteServiceSOAP)"/>
</reference>
</composite>
如下给出了bigbank.AccountData构件的定义
<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
targetNamespace="http://bigbank.com"
name="bigbank.AccountData">
<service name="accountdataService" promote="AccountData">
<interface.java interface="services.accountdata.AccountDataService"/>
</service>
<component name="AccountData">
<implementation.java class="services.accountdata.AccountDataImpl"/>
</component>
</composite>
部署装配集
下面的装配图给出了SCA域中的bigbank.account构件的配置。我们经过创建另一个构件配置了一个实现(在我们例子中是bigbank.Account构件)到SCA域中。创建的构件通过包含方式添加到域中。域自身就如构件一样工作,并且其配置通过对其他构件的包含来设置。
注:许多情况下,组件配合完整的配置信息使得他们在SCA域中是已经可以使用的组件。SCA提供了为这些实现的部署提供了直接的方式。
以下代码片段给出了bigbank.AccountManagement构件的定义,该构件创建了前面提到的bigbank.Account构件的配置化了的实例。它演示了当前属性是如何设置的,也展示了stock quote web service的endpoint地址是如何被覆盖的:
<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
xmlns:bb="http://bigbank.com"
targetNamespace="http://bigbank.com"
name="bigbank.AccountManagement">
<component name="bigbank.Account">
<implementation.composite name="bb:bigbank.Account" />
<property name="currency">EURO</property>
<reference name="stockQuoteService">
http://www.eurosq.com/SQService
</reference>
</component>
</composite>
下列代码片段展示了bigbank.Client构件的定义。该构件创建了bigbank.Webclient构件的配置化实例。Bigbank.Webclient构件的详细信息请查看我翻译的BigBank案例。Bigbank.Webclient构件的accountService引用被连线到bigbank.Account构件的accountService上。
<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
xmlns:bb="http://bigbank.com"
targetNamespace="http://bigbank.com"
name="bigbank.Client">
<component name="bigbank.Webclient">
<implementation.composite name="bb:bigbank.Webclient" />
<reference name="accountService" target="bigbank.account/accountService"/>
</component>
</composite>