﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-每日一得-随笔分类-SOA</title><link>http://www.blogjava.net/alex/category/13521.html</link><description>不求多得,只求一得
about java,hibernate,spring,design,database,linux,etc.
&lt;br/&gt;&lt;br/&gt;
最近关心的内容关键字:web快速开发方案，建模,workshop studio,Ajax
</description><language>zh-cn</language><lastBuildDate>Tue, 27 Feb 2007 14:56:09 GMT</lastBuildDate><pubDate>Tue, 27 Feb 2007 14:56:09 GMT</pubDate><ttl>60</ttl><item><title>[转]SOA实践 -- 使用IoC和AOP重构SOA应用</title><link>http://www.blogjava.net/alex/archive/2006/07/28/60552.html</link><dc:creator>Alex</dc:creator><author>Alex</author><pubDate>Fri, 28 Jul 2006 05:29:00 GMT</pubDate><guid>http://www.blogjava.net/alex/archive/2006/07/28/60552.html</guid><wfw:comment>http://www.blogjava.net/alex/comments/60552.html</wfw:comment><comments>http://www.blogjava.net/alex/archive/2006/07/28/60552.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/alex/comments/commentRss/60552.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/alex/services/trackbacks/60552.html</trackback:ping><description><![CDATA[
		<p>级别: 初级</p>
		<p>
				<a href="http://www-128.ibm.com/developerworks/cn/webservices/ws-refactoring/?S_TACT=105AGX52&amp;S_CMP=techccid#author"> 易立</a>, IBM 中国软件开发实验室 SOA设计中心 高级软件工程师<br /><a href="http://www-128.ibm.com/developerworks/cn/webservices/ws-refactoring/?S_TACT=105AGX52&amp;S_CMP=techccid#author"> 赵勇</a>, IBM 中国软件开发实验室 SOA设计中心 高级软件工程师<br /></p>
		<p>2006 年  4 月  20 日</p>
		<blockquote>在本文中，作者通过一个Web Service访问的实例，具体描述了SOA应用中所遇到的一系列具体问题，并描述如何利用IoC和AOP等技术进行代码重构，从而构建结构更加良好、灵活的SOA应用。</blockquote>
		<!--START RESERVED FOR FUTURE USE INCLUDE FILES-->
		<!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters -->
		<!--END RESERVED FOR FUTURE USE INCLUDE FILES-->
		<p>
				<a name="IDA2CANB">
						<span class="atitle">1.引言</span>
				</a>
		</p>
		<p>SOA是一种构造分布式系统的方法，它将业务应用功能以服务的形式提供出来，以便更好的复用、组装和与外部系统集成，从而降低开发成本，提高开发效率。SOA的目标是为企业构建一个灵活，可扩展的IT基础架构来更好地支持随需应变的商务应用。</p>
		<p>随着SOA技术和产品的不断成熟，现在越来越多的用户开始了解并认同SOA的理念，但对SOA项目的实施还缺乏信心。其主要原因是：SOA应用开发还相对比较复杂。</p>
		<p>一年多来，本文作者所在的部门已经从事了许多国内外的SOA项目的实施和支持工作，积累了许多SOA应用开发经验。我们希望能够通过一系列的文章与读者分享这些想法，帮助您更好地构建SOA应用。</p>
		<p>本
文将从Web Service调用入手，在解决一系列具体问题的过程中，使用IoC (Inversion of Control) 和AOP
(Aspect- Oriented Programming) 等方法重构Web Service的访问代码，使得业务逻辑与Web
Service访问解耦，为您提供一个更加灵活和易于扩展的访问模式。</p>
		<p>Spring是一个流行的轻量级容器，对IoC和AOP提供了良好的
支持。本文为您提供了一个基于Spring的实现供您下载学习。示例代码工程使用Eclipse3.1/3.02和JDK1.4开发,
您还需要Spring 1.2.5和Axis1.3提供的支持。详细的下载信息请参见参考资源部分。</p>
		<br />
		<table border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td>
										<img alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" width="100%" />
										<br />
										<img src="http://www.ibm.com/i/c.gif" alt="" border="0" height="6" width="8" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" align="right" cellpadding="0" cellspacing="0">
				<tbody>
						<tr align="right">
								<td>
										<img alt="" src="http://www.ibm.com/i/c.gif" height="4" width="100%" />
										<br />
										<table border="0" cellpadding="0" cellspacing="0">
												<tbody>
														<tr>
																<td valign="middle">
																		<img alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" border="0" height="16" width="16" />
																		<br />
																</td>
																<td align="right" valign="top">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/webservices/ws-refactoring/?S_TACT=105AGX52&amp;S_CMP=techccid#main">
																				<b>回页首</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="IDAGDANB">
						<span class="atitle">2.Web Service调用</span>
				</a>
		</p>
		<p>Web Service是目前实现SOA应用的一项基本的，适用的技术，它为服务的访问提供了一个被广泛接受的开放标准。为了便于说明问题，我们将使用XMethods 网站（<a href="http://www.xmethods.net/">http://www.xmethods.net/</a>）发布的货币兑换服务作为示例。并针对JAX-RPC 1.1，说明如何编写Web Service 的调用代码。</p>
		<p>
				<a name="IDARDANB">
						<span class="smalltitle">2.1 示例说明</span>
				</a>
		</p>
		<p>http://xmethods.net  作为最早推出Web Service实际示例的网站，提供了很多优秀的Web Service 样例。其中有一个汇率计算服务，可以返回两个国家之间的货币兑换比例。获取该服务的详细信息，请参考该服务的服务描述文档（<a href="http://www.xmethods.net/sd/2001/CurrencyExchangeService.wsdl">获取WSDL 文档</a>） 。在此就不具体解析该服务描述文档了。读者可以从WSDL2Java生成的接口中了解该服务的用法：</p>
		<br />
		<table bgcolor="#eeeeee" border="1" cellpadding="5" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<br />public interface CurrencyExchangePortType extends java.rmi.Remote {<br />public float getRate(String country1, String country2) throws java.rmi.RemoteException;<br />}<br /></code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>
				<a name="IDADEANB">
						<span class="smalltitle">2.2 客户端调用方法</span>
				</a>
		</p>
		<p>JAX-RPC作为Java平台的RPC服务调用标准接口，为Web Service客户端调用提供了3种方法，分别是DII，动态代理，和静态Stub。
DII（Dynamic Invocation Interface）采用直接调用方式，可以在程序中设置诸多的调用属性，使用较为灵活，但是调用过程却相对繁琐复杂，易造成代码膨胀且可重用性低，每次调用不同的Web Service都要重复进行大量编码。</p>
		<p>JAX-RPC中动态代理（Dynamic Proxy）的方法实现对Web Service的动态调用，可以在运行时根据用户定义的Client端接口创建适配对象。从而避免了直接操作底层的接口，减少了客户端的冗余，屏蔽了调用相关的复杂性。</p>
		<p>使
用静态Stub和Service
Locator是目前最常用的调用方式。JAX-RPC使用静态的Stub方式包装对底层接口的调用，从而提供一种更为简便的调用方式。使用该方式需要利
用支持环境（比如Axis）所提供的工具根据WSDL预生成Web
Service客户端的实现代码。因此如果服务的WSDL发生变化，就必须重新生成新的客户端代码并进行重新部署。</p>
		<p>为了更详细的了解静态Stub的调用方式，您可以将示例代码的WebServiceClient.jar导入到您现有Eclipse工作区之中。</p>
		<p>客户端生成代码包括如下4个类：如图 1 所示：</p>
		<br />
		<a name="IDAOEANB">
				<b>图 1： 客户端代码类图</b>
		</a>
		<br />
		<img src="http://www-128.ibm.com/developerworks/cn/webservices/ws-refactoring/images/image002.gif" alt="图 1： 客户端代码类图" border="0" height="269" width="476" />
		<br />
		<p>在上图中包括的几个类中：</p>
		<p>CurrencyExchangePortType：服务端点接口，定义了Web Service的方法签名。</p>
		<p>CurrencyExchangeService：Service接口，定义了获取服务端点接口的方法。</p>
		<p>CurrencyExchangeServiceLocator：ServiceLocator类，实现了Service接口。</p>
		<p>CurrencyExchangeBindingStub： Stub实现类，实现了服务端点接口，封装了对Web Service访问的底层逻辑。</p>
		<p>使用Stub调用Web Service的过程也非常简单，读者可以参考清单 1：</p>
		<br />
		<a name="IDABFANB">
				<b>清单 1：Web Service 调用代码示例</b>
		</a>
		<br />
		<table bgcolor="#eeeeee" border="1" cellpadding="5" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<br />try {<br />	//创建ServiceLocator<br />	CurrencyExchangeServiceLocator locator = new<br />	CurrencyExchangeServiceLocator();<br />	//设定端点地址<br />	URL endPointAddress = new URL("http://services.xmethods.net:80/soap");<br />	//创建Stub实例<br />	CurrencyExchangePortType stub =<br />	locator.getCurrencyExchangePort(endPointAddress);<br />	//设定超时为120秒<br />	((CurrencyExchangeBindingStub)stub).setTimeout(120000);<br />	//调用Web Service计算人民币与美元的汇率<br />	float newPrice = stub.getRate("China", "USA") * 100;<br />} catch (MalformedURLException mex) {<br />	//...<br />} catch (ServiceException sex) {<br />	//...<br />} catch (RemoteException rex) {<br />	//...<br />}<br /></code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<table border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td>
										<img alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" width="100%" />
										<br />
										<img src="http://www.ibm.com/i/c.gif" alt="" border="0" height="6" width="8" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" align="right" cellpadding="0" cellspacing="0">
				<tbody>
						<tr align="right">
								<td>
										<img alt="" src="http://www.ibm.com/i/c.gif" height="4" width="100%" />
										<br />
										<table border="0" cellpadding="0" cellspacing="0">
												<tbody>
														<tr>
																<td valign="middle">
																		<img alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" border="0" height="16" width="16" />
																		<br />
																</td>
																<td align="right" valign="top">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/webservices/ws-refactoring/?S_TACT=105AGX52&amp;S_CMP=techccid#main">
																				<b>回页首</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="IDAJFANB">
						<span class="atitle">3.重构Web Service调用代码</span>
				</a>
		</p>
		<p>
				<a name="IDAOFANB">
						<span class="smalltitle">3.1 实例代码中的"坏味道"</span>
				</a>
		</p>
		<p>上面的基于Service Locator的Web Service访问代码虽然简单但暴露出以下几个问题：</p>
		<p>1．访问Web Service所需的配置代码被嵌入应用逻辑之中<br />
	在Web Service调用中，我们需要设定一系列必要的参数。比如：服务端点地址、用户名/密码、超时设定等等。这些参数在开发和运行环境中都有可能发生变化。我们必须提供一种机制：在环境变化时，不必修改源代码就可以改变Web Service的访问配置。</p>
		<p>2  客户端代码与Web Service访问代码绑定<br />
在上面的代码中，业务逻辑与Web
Service的Stub创建和配置代码绑定在一起。这也不是一种良好的编程方式。客户端代码只应关心服务的接口，而不应关心服务的实现和访问细节。比
如，我们既可以通过Web Service的方式访问远程服务，也可以通过EJB的方式进行访问。访问方式对业务逻辑应该是透明的。</p>
		<p>这
种分离客户端代码与服务访问代码的方式也有利于测试。这样在开发过程中，负责集成的程序员就可能在远程服务还未完全实现的情况下，基于服务接口编写集成代
码，并通过编写POJO（Plain Old Java
Object）构建伪服务实现来进行单元测试和模拟运行。这种开发方式对于保证分布式系统代码质量具有重要意义。</p>
		<p>因此，为了解决上面的问题我们需要：</p>
		<p>1、将Web Service访问的配置管理与代码分离；</p>
		<p>2、解除客户端代码与远程服务之间的依赖关系；</p>
		<p>
				<a name="IDAAGANB">
						<span class="smalltitle">3.2 利用IoC模式进行重构代码</span>
				</a>
		</p>
		<p>我
们先介绍在Core J2EE Patterns一书中提到的一种业务层模式：Business
Delegate。它所要解决的问题是屏蔽远程服务访问的复杂性。它的主要思想就是将Business
Delegate作为远程服务的客户端抽象，隐藏服务访问细节。Business
Delegate还可以封装并改变服务调用过程，比如将远程服务调用抛出的异常（例如RemoteException）转换为应用级别的异常类型。</p>
		<p>其类图如图 2 所示：</p>
		<br />
		<a name="IDAIGANB">
				<b>图 2：Business Delegate 模式的类图图解</b>
		</a>
		<br />
		<img src="http://www-128.ibm.com/developerworks/cn/webservices/ws-refactoring/images/image004.gif" alt="图 2：Business Delegate 模式的类图图解" border="0" height="154" width="554" />
		<br />
		<p>Business
Delegate模式实现很好地实现了客户端与远程访问代码的解耦，但它并不关注Delegate与远程服务之间的解耦。为了更好解决Business
Delegate和远程服务之间的依赖关系，并更好地进行配置管理，我们可以用IoC模式来加以解决。</p>
		<p>IoC（Inversion of
Contro）l意为控制反转，其背后的概念常被表述为"好莱坞法则"："Don't call me, I'll call you."
IoC将一部分责任从应用代码交给framework（或者控制器）来做。通过IoC可以实现接口和具体实现的高度分离，降低对象之间的耦合程度。
Spring是一个非常流行的IoC容器，它通过配置文件来定义对象的生命周期和依赖关系，并提供了良好的配置管理能力。</p>
		<p>现在我们来重构我们的Web Service应用程序，我们首先为Business Delegate定义一个接口类型，它提供了一个应用级组件接口，所有客户端都应通过它来执行汇率计算，而不必关心实现细节，如清单 2 所示：</p>
		<br />
		<a name="IDAYGANB">
				<b>清单 2：接口定义的代码示例</b>
		</a>
		<br />
		<table bgcolor="#eeeeee" border="1" cellpadding="5" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<br />
														<br />Public interface CurrencyExchangeManager {<br />	//货币兑换计算<br />	//新价格 = 汇率 * 价格<br />public float calculate(String country1, String country2, float price) <br />throws CurrencyExchangeException;<br />}<br /></code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>Business Delegate的实现非常简单，主要工作是包装汇率计算 Web Service的调用，如清单 3 所示。</p>
		<br />
		<a name="IDABHANB">
				<b>清单 3：Business Delegate的代码示例</b>
		</a>
		<br />
		<table bgcolor="#eeeeee" border="1" cellpadding="5" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<br />public class CurrencyExchangeManagerImpl implements CurrencyExchangeManager {<br />	//服务实例<br />	private CurrencyExchangePortType stub;<br />	//获取服务实例<br />	public CurrencyExchangePortType getStub() {<br />		return stub;<br />	}<br />	//设定服务实例<br />	public void setStub(CurrencyExchangePortType stub) {<br />		this.stub = stub;<br />	}<br />	//实现货币兑换<br />	public float calculate(String country1, String country2, float price)<br />throws CurrencyExchangeException {<br />		try {<br />			//通过Stub调用WebService<br />			float rate = stub.getRate(country1, country2);<br />			return rate * price;<br />		} catch (RemoteException rex) {<br />			throw new CurrencyExchangeException(<br />					"Failed to get exchange rate!", rex);<br />		}<br />	}<br />}<br /></code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>下面我们需要讨论如何利用Spring的IoC机制，来创建和配置对象，并定义它们的依赖关系。</p>
		<p>Spring
利用类工厂来创建和配置对象。在Spring框架中，已经为基于JAX－RPC的Web
Service调用提供了一个客户端代理的类工厂实现：JaxRpcPortProxyFactoryBean。在配置文件bean.xml中，我们将使
用JaxRpcPortProxyFactoryBean来创建和配置Web
Service的客户端代理"CurrencyExchangeService"，如清单 5
所示。我们还将定义一个名为"CurrencyExchangeManager"的CurrencyExchangeManagerImpl实例，并建立
它与CurrencyExchangeService之间的依赖关系。有关Spring
配置和JaxRpcPortProxyFactoryBean的使用细节请参见参考资料。</p>
		<br />
		<a name="IDALHANB">
				<b>清单 5：bean.xml的配置文件</b>
		</a>
		<br />
		<table bgcolor="#eeeeee" border="1" cellpadding="5" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<br />
														<br />&lt;?xml version="1.0" encoding="utf-8"?&gt;<br />&lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"<br />"http://www.springframework.org/dtd/spring-beans.dtd"&gt;<br />&lt;beans&gt;<br />	&lt;bean id="CurrencyExchangeService"<br />	class="org.springframework.remoting.jaxrpc.JaxRpcPortProxyFactoryBean"&gt;<br />		&lt;property name="serviceInterface"&gt;	<br />		&lt;value&gt;net.xmethods.www.sd.CurrencyExchangeService_wsdl.<br />		CurrencyExchangePortType&lt;/value&gt;<br />		&lt;/property&gt;<br />		&lt;property name="wsdlDocumentUrl"&gt;		<br />		&lt;value&gt;http://www.xmethods.net/sd/2001/CurrencyExchangeService.<br />		wsdl&lt;/value&gt;<br />		&lt;/property&gt;<br />		&lt;property name="namespaceUri"&gt;<br />			&lt;value&gt;http://www.xmethods.net/sd/CurrencyExchangeService.<br />			wsdl&lt;/value&gt;<br />		&lt;/property&gt;<br />		&lt;property name="serviceName"&gt;<br />			&lt;value&gt;CurrencyExchangeService&lt;/value&gt;<br />		&lt;/property&gt;<br />		&lt;property name="portName"&gt;<br />			&lt;value&gt;CurrencyExchangePort&lt;/value&gt;<br />		&lt;/property&gt;<br />		&lt;property name="endpointAddress"&gt;<br />			&lt;value&gt;http://services.xmethods.net:80/soap&lt;/value&gt;		<br />		&lt;/property&gt;<br />	&lt;/bean&gt;	<br />	&lt;bean id="CurrencyExchangeManager"<br />	class="test.ws.CurrencyExchangeManagerImpl"&gt;<br />		&lt;property name="stub"&gt;<br />			&lt;ref bean="CurrencyExchangeService"/&gt;<br />		&lt;/property&gt;<br />	&lt;/bean&gt;<br />&lt;/beans&gt;<br /></code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>最后我们创建一个测试程序来验证我们的代码，如清单6 所示：</p>
		<br />
		<a name="IDAUHANB">
				<b>清单 6：测试代码</b>
		</a>
		<br />
		<table bgcolor="#eeeeee" border="1" cellpadding="5" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<br />
														<br />public class Main {<br />	// For test only<br />	public static void main(String[] args) {<br />		// Spring Framework将根据配置文件创建并配置CurrencyExchangeManager实例<br />		ApplicationContext ctx = new FileSystemXmlApplicationContext("bean.xml");<br />		// 获取CurrencyExchangeManager实例<br />		CurrencyExchangeManager manager = (CurrencyExchangeManager) ctx<br />				.getBean("CurrencyExchangeManager");<br />		try {<br />			System.out.println(manager.calculate("China", "USA", 100));<br />			System.out.println(manager.calculate("China", "Japan", 200));<br />			System.out.println(manager.calculate("China", "USA", 200));<br />		} catch (Exception ex) {<br />			ex.printStackTrace();<br />		}<br />	}<br />}<br /></code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>此时运行测试客户端，等待片刻将会看见测试结果，如清单 7 所示：</p>
		<br />
		<a name="IDA3HANB">
				<b>清单 7：测试结果。</b>
		</a>
		<br />
		<table bgcolor="#eeeeee" border="1" cellpadding="5" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<br />12.34<br />2853.26<br />24.68<br /></code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>注：该结果会随着汇率的变化而出现不同的值。</p>
		<p>该程序的类图和顺序图如图3及图4所示：</p>
		<br />
		<a name="IDALQMNB">
				<b>图 3：示例程序的类图</b>
		</a>
		<br />
		<img src="http://www-128.ibm.com/developerworks/cn/webservices/ws-refactoring/images/image006.jpg" alt="图 3：示例程序的类图" border="0" height="223" width="553" />
		<br />
		<p>从
上面的类图我们可以看到，我们的测试程序（Main.java）通过Spring框架获取了BusinessDelegate的实例。而且Spring
框架还会根据配置中的依赖关系，在运行时将Web Service的客户端代理"
注射"到CurrencyExchangeManagerImpl实例中，这就是依赖注入（<a href="http://www.martinfowler.com/articles/injection.html">Dependency Injection</a>）。通过这种方式解决了应用逻辑和BusinessDelegate之间的依赖关系，以及BusinessDelegate的实现与远程服务之间的依赖关系，如图 4 所示。</p>
		<br />
		<a name="IDA5QMNB">
				<b>图 4:  示例程序的顺序图</b>
		</a>
		<br />
		<img src="http://www-128.ibm.com/developerworks/cn/webservices/ws-refactoring/images/image008.jpg" alt="图 4:  示例程序的顺序图" border="0" height="252" width="553" />
		<br />
		<p>Spring
框架提供的ApplicationContext实现会根据配置文件中的描述信息来实现对象生命周期管理，配置管理以及依赖管理等功能。这一切对于应用程
序是透明的，应用程序代码只依赖接口进行编程，而无需考虑其它复杂问题。无论是Web
Service的配置发生变化，或是改用不同的服务实现时，都不会对客户端应用代码的产生影响。这很好地实现了业务逻辑与Web
Service调用之间的解耦。</p>
		<p>
				<a name="IDANRMNB">
						<span class="smalltitle">3.3 构建自己的 Web Service代理工厂</span>
				</a>
		</p>
		<p>Spring
所提供的JaxRpcPortProxyFactoryBean封装了构造Web
Service客户端代理的细节，可以通过参数配置来创建Dynamic Proxy和DII类型的Web
Service客户端代理。（如果您希望深入了解其实现细节可以参考org.springframework.remoting.jaxrpc包下的源代
码。）但由于JaxRpcPortProxyFactoryBean需要使用者对WSDL中Port，Service，名空间等概念有深入的了解；而且如
果Web
Service使用了复杂数据类型，开发人员需要手工定义类型映射代码。所以JaxRpcPortProxyFactoryBean并不适合Web
Service的初学者来使用。</p>
		<p>为了进一步简化Web
Service代理的创建，并帮助读者更好地理解类工厂在Spring框架下的作用。我们提供了一个基于静态Stub的Web
Service客户端代理工厂实现。其核心代码非常简单，就是通过ServiceLocator提供的方法来创建Web Service客户端代理。</p>
		<p>其主要代码如清单8所示：</p>
		<br />
		<a name="IDAVRMNB">
				<b>清单8：静态代理工厂的代码</b>
		</a>
		<br />
		<table bgcolor="#eeeeee" border="1" cellpadding="5" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<br />public class WebServiceStubFactoryBean implements FactoryBean, <br />InitializingBean {<br />	private Class serviceInterface;<br />	private Class serviceLocator;<br />	private Object stub;<br />     …<br />	public void afterPropertiesSet() throws Exception {<br />         //利用serviceLocator和服务接口创建Web Service客户端代理<br />		stub = ((javax.xml.rpc.Service)<br />		serviceLocator.newInstance()).getPort(serviceInterface);<br />	    //为Stub设定endpointAddress，usernam, 超时等参数<br />		preparePortStub((javax.xml.rpc.Stub) stub);<br />	}<br />	public Object getObject() {<br />          // 返回客户端代理<br />		return stub;<br />	}<br />	public Class getObjectType() {<br />          // 返回服务接口<br />		return serviceInterface;<br />	}<br />	public boolean isSingleton() {<br />		return true;<br />	}<br />}<br /></code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>我们需要修改配置文件bean.xml中有关Web Service代理创建的部分，让新的Web Service 代理工厂发挥作用。如清单9所示：</p>
		<br />
		<a name="IDA4RMNB">
				<b>清单9：修改后的bean.xml的配置文件</b>
		</a>
		<br />
		<table bgcolor="#eeeeee" border="1" cellpadding="5" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<br />
														<br />&lt;bean id="CurrencyExchangeService" class="test.ws.WebServiceStubFactoryBean"&gt;<br />	&lt;property name="serviceInterface"&gt;<br />	&lt;value&gt;net.xmethods.www.sd.CurrencyExchangeService_wsdl.CurrencyExchangePortType&lt;/value&gt;<br />	&lt;/property&gt;<br />	&lt;property name="serviceLocator"&gt;<br />	&lt;value&gt;net.xmethods.www.sd.CurrencyExchangeService_wsdl.CurrencyExchangeServiceLocator&lt;/value&gt;<br />	&lt;/property&gt;<br />	&lt;property name="endpointAddress2"&gt;<br />		&lt;value&gt;http://services.xmethods.net:80/soap&lt;/value&gt;<br />	&lt;/property&gt;<br />	&lt;property name="timeout"&gt;<br />		&lt;value&gt;120000&lt;/value&gt;<br />	&lt;/property&gt;<br />&lt;/bean&gt;<br /></code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>得益于Spring框架，虽然我们已经替换了对象的类工厂，却并不需要更改应用代码。通过Spring框架的IoC机制，我们可以完全使用面向接口的编程方式，而将实现的创建、配置和依赖管理交由Spring在运行时完成。即使实现发生了变化，也不需要改变应用程序结构。</p>
		<br />
		<table border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td>
										<img alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" width="100%" />
										<br />
										<img src="http://www.ibm.com/i/c.gif" alt="" border="0" height="6" width="8" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" align="right" cellpadding="0" cellspacing="0">
				<tbody>
						<tr align="right">
								<td>
										<img alt="" src="http://www.ibm.com/i/c.gif" height="4" width="100%" />
										<br />
										<table border="0" cellpadding="0" cellspacing="0">
												<tbody>
														<tr>
																<td valign="middle">
																		<img alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" border="0" height="16" width="16" />
																		<br />
																</td>
																<td align="right" valign="top">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/webservices/ws-refactoring/?S_TACT=105AGX52&amp;S_CMP=techccid#main">
																				<b>回页首</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="IDAHSMNB">
						<span class="atitle">4.新的思考</span>
				</a>
		</p>
		<p>故事并没有结束，在开发过程中，我们又遇到了一系列关于Web Service调用的问题。</p>
		<p>
				<a name="IDANSMNB">
						<span class="smalltitle">4.1性能</span>
				</a>
		</p>
		<p>系
统性能是分布式应用中的一个重要问题。许多用户都担心由Web
Service技术所引入的额外开销是否会影响到产品的性能。随着技术的不断发展，Web
Service引擎性能已经有了很大提高，一般来说使用Web
Service的系统的性能可以满足绝大部分应用的需求。但在特定情况下，如果系统性能无法满足客户需求，我们首先需要对系统性能进行科学地分析和测定才
能定位真正的性能瓶颈。这个问题在上文简单的示例中并不难解决，只需要在Web
Service调用前后加入日志代码记录调用时间即可实现。但在实际系统中，比如一个产品目录的Web
Service可能提供数十种查询方法，而程序中很多组件都会依赖于该服务提供的查询功能。如果在系统中所有的地方加入性能测定代码，这个工作就变得非常
繁琐和困难。我们需要用一种更加优雅的解决方式，在增添新功能的同时并不影响系统代码或结构。</p>
		<p>
				<a name="IDATSMNB">
						<span class="smalltitle">4.2缓存</span>
				</a>
		</p>
		<p>在
项目实践中，一个有效的改善Web Service系统性能的方法就是利用缓存来减少Web
Service的重复调用。在具体实现中我们可以采用客户端缓存和服务器端缓存等不同方式，他们具有不同的特点和适用范围。在本文例子中，我们希望实现客
户端缓存来提高系统性能。但由于Web Service业务逻辑的差别，我们希望能够为特定的Web
Service提供特定的缓存策略，而且这些策略应该是能够被灵活配置的，它们不应于应用程序的逻辑代码耦合在一起。</p>
		<p>
				<a name="IDAZSMNB">
						<span class="smalltitle">4.3故障恢复：</span>
				</a>
		</p>
		<p>对
于Web Service应用，系统的可用性也是一个需要考虑的重要问题。在运行时由于网络运行环境的复杂性和不确定性，用户希望能够对Web
Service访问提供一定的故障恢复机制：比如重试或者访问备份服务（当系统在调用Web Service失败后，使用备份Web
Service的服务地址来继续访问）。这些故障恢复策略应该是可配置的，对应用逻辑透明的。</p>
		<br />
		<table border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td>
										<img alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" width="100%" />
										<br />
										<img src="http://www.ibm.com/i/c.gif" alt="" border="0" height="6" width="8" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" align="right" cellpadding="0" cellspacing="0">
				<tbody>
						<tr align="right">
								<td>
										<img alt="" src="http://www.ibm.com/i/c.gif" height="4" width="100%" />
										<br />
										<table border="0" cellpadding="0" cellspacing="0">
												<tbody>
														<tr>
																<td valign="middle">
																		<img alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" border="0" height="16" width="16" />
																		<br />
																</td>
																<td align="right" valign="top">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/webservices/ws-refactoring/?S_TACT=105AGX52&amp;S_CMP=techccid#main">
																				<b>回页首</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="IDA5SMNB">
						<span class="atitle">5.使用AOP解决SOA应用中的Crosscutting Concern</span>
				</a>
		</p>
		<p>通过对上边一系列问题的分析，读者也许会发现这些问题并不是Web Service访问的核心问题，但会影响系统中许多不同的组件。而且其中一些问题需要我们能够灵活配置不同的实现策略，因此我们不应该将处理这些问题的代码与应用代码混合。</p>
		<p>下
面我们将利用AOP（Aspect-Oriented
Programming）提供的方法来解决上述的问题。AOP是一种新兴的方法学，它最基本的概念就是关注隔离（Separation of
Concern）。AOP提供了一系列的技术使得我们能够从代码中分离那些影响到许多系统模块的crosscutting
concerns，并将他们模块化为Aspects。AOP的主要目的仍然是解耦，在分离关注点后，才能将关注点的变更控制一定范围内，增加程序的灵活
性，才能使得关注能够根据需求和环境作出随时调整。</p>
		<p>我们将利用Spring所提供的AOP功能支持来解决以上问题。这里我们只简单地介绍涉及到的AOP基本概念以及实现，如果您希望更好地了解AOP的概念以及Spring AOP支持的细节请参见参考资料。</p>
		<ul>
				<li>Joinpoint 是程序的运行点。在Spring AOP中，一个Joinpoint对应着一个方法调用。</li>
				<li>Advice 定义了AOP框架在特定的Joinpoint的处理逻辑。Spring AOP框架通过interceptor方式实现了advice，并且提供了多种advice类型。其中最基本的"around advice"会在一个方法调用之前和之后被执行。</li>
		</ul>
		<p>下面我们将利用Spring提供的MethodInterceptor来为Web Service调用实现我们的定义的处理逻辑。</p>
		<p>
				<a name="IDALTMNB">
						<span class="smalltitle">5.1 PerformanceMonitorInterceptor </span>
				</a>
		</p>
		<p>性能测量是AOP最简单的例子之一，我们可以直接利用Spring提供的实现在bean.xml中声明我们的WebServicePerformanceMonitorInterceptor。</p>
		<p>
				<a name="IDARTMNB">
						<span class="smalltitle">5.2 CacheInterceptor</span>
				</a>
		</p>
		<p>为
了不引入缓存策略的复杂性，我们只提供了一个利用HashMap的简单实现：它利用 Web
Service的调用参数列表作为HashMap键值。在Web
Service调用之前，首先检查缓存中是否拥有与现在参数列表相同的项，如果有则返回缓存的结果，否则调用Web
Service并将&lt;参数列表，结果&gt;记录在HashMap中。在实际应用中，您应该根据具体情况来选择、构造适合Web
Service的业务特性的Cache实现，也可以采用成熟的Cache实现。</p>
		<p>在下面代码实现中有一个生成Web Service调用主键的小技巧。因为Web Service引擎要求所有调用参数必须是可序列化的，所以我们可以利用Java提供的序列化功能来实现对象的克隆。如清单10所示：</p>
		<br />
		<a name="IDAYTMNB">
				<b>清单10：SimpleCacheInterceptor的代码示例</b>
		</a>
		<br />
		<table bgcolor="#eeeeee" border="1" cellpadding="5" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<br />
														<br />public class SimpleCacheInterceptor implements MethodInterceptor {<br />	private Map cache = new HashMap();<br />	private Object cloneObject(Object obj) throws Exception {<br />		Object newObj = null;<br />		if (obj != null) {<br />			// 通过序列化/反序列化来克隆对象<br />			ByteArrayOutputStream bos = new ByteArrayOutputStream();<br />			ObjectOutputStream out = new ObjectOutputStream(bos);<br />			out.writeObject(obj);<br />			out.flush();<br />			out.close();<br />			ObjectInputStream in = new ObjectInputStream(<br />					new ByteArrayInputStream(bos.toByteArray()));<br />			newObj = in.readObject();<br />		}<br />		return newObj;<br />	}<br />	//基于参数列表数组，生成用于HashMap的键值<br />public Object generateKey(Object[] args) throws Exception {<br />		Object[] newArgs = (Object[]) cloneObject(args);<br />		List key = Arrays.asList(newArgs);<br />		return key;<br />	}<br />	//实现使用缓存技术的invoke方法<br />	public Object invoke(MethodInvocation methodInvocation) throws Throwable {<br />		Object result = null;<br />		Object data = null;<br />		Object key = null;<br /><br />		try {<br />			key = generateKey(methodInvocation.getArguments());<br />			data = cache.get(key);<br />		} catch (Exception ex) {<br />			logger.error("Failed to find from the cache", ex);<br />		}<br /><br />		if (data == null) {<br />			//如果Cache中没有缓存结果，调用服务执行生成用于HashMap的键值<br />			result = methodInvocation.proceed();<br />			try {<br />				data = cloneObject(result);<br />				cache.put(key, data);<br />			} catch (Exception ex) {<br />				logger.error("Failed to cache the result!", ex);<br />			}<br />		} else {<br />			result = data;<br />		}<br />		return result;<br />	}<br />}<br /></code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>
				<a name="IDAAUMNB">
						<span class="smalltitle">5.3 FailoverInterceptor</span>
				</a>
		</p>
		<p>下面代码提供了一个基于服务备份切换的故障恢复实现，在运行时，如果Interceptor检测到服务调用由于网络故障抛出异常时，它将使用备份服务的端点地址并重新调用。如清单11所示：</p>
		<br />
		<a name="IDAGUMNB">
				<b>清单 11： SimpleFailoverInterceptor的代码示例</b>
		</a>
		<br />
		<table bgcolor="#eeeeee" border="1" cellpadding="5" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<br />
														<br />public class SimpleFailoverInterceptor implements MethodInterceptor {	…<br />     …<br />	//实现支持端点运行时切换的invoke方法<br />	public Object invoke(MethodInvocation methodInvocation) throws Throwable {<br />		Object result = null;<br />		try {<br />			result = methodInvocation.proceed();<br />		} catch (Throwable ex) {<br />	        if (isNetworkFailure(ex)) {<br />                  //切换服务端点地址<br />				switchEndPointAddress((Stub) methodInvocation.getThis());<br />				result = methodInvocation.proceed();<br />			} else {<br />				throw ex;<br />			}<br />		}<br />		return result;<br />	}<br />}<br /></code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>为了支持备份服务切换的功能，我们在WebServicePortProxyFactoryBean中为填加了配置参数"endpointAddress2"，它会在创建的Web Service客户端代理对象中记录备份URL。</p>
		<p>我
们可以在CurrencyExchangeService加入下列参数来试验SimpleFailoverInterceptor的功能。其中第一个端点
地址为一个错误的URL。在第一次调用服务时，SimpleFailoverInterceptor会侦测到网络故障的发生，并自动切换使用第二个端点地
址继续访问。如清单12所示：</p>
		<br />
		<a name="IDAQUMNB">
				<b>清单12：配置文件种增加的属性</b>
		</a>
		<br />
		<table bgcolor="#eeeeee" border="1" cellpadding="5" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<br />
														<br />
														<br />&lt;property name="endpointAddress"&gt;<br />	&lt;value&gt;http://localhost/wrong_endpoint_address&lt;/value&gt;<br />&lt;/property&gt;<br />&lt;property name="endpointAddress2"&gt;<br />	&lt;value&gt;http://services.xmethods.net:80/soap&lt;/value&gt;<br />&lt;/property&gt;<br /></code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>
				<a name="IDAYUMNB">
						<span class="smalltitle">5.4配置文件和运行结果</span>
				</a>
		</p>
		<p>现
在我们需要在Spring配置文件中，为所有interceptor添加定义，并描述如何为CurrencyExchangeService构建AOP
Proxy。需要指出的是，我们要在interceptorName列表中声明interceptor链的调用顺序，还要将原有
CurrencyExchangeManager引用的stub对象替换为新AOP Proxy。如清单13所示：</p>
		<br />
		<a name="IDA4UMNB">
				<b>清单13：修改后的配置文件片段</b>
		</a>
		<br />
		<table bgcolor="#eeeeee" border="1" cellpadding="5" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<br />
														<br />
														<br />&lt;bean id="WebServicePerformanceMonitorInterceptor"<br />class="org.springframework.aop.interceptor.PerformanceMonitorInterceptor"&gt;<br />	&lt;property name="prefix"&gt;<br />		&lt;value&gt;Web Service &lt;/value&gt;<br />	&lt;/property&gt;<br />	&lt;property name="suffix"&gt;<br />		&lt;value&gt;&lt;/value&gt;<br />	&lt;/property&gt;<br />&lt;/bean&gt;<br />&lt;bean id="CacheInterceptor" class="test.ws.SimpleCacheInterceptor"/&gt;<br />&lt;bean id="FailoverInterceptor" class="test.ws.SimpleFailoverInterceptor"/&gt;	<br />&lt;bean id="CurrencyExchangeProxy"<br />class="org.springframework.aop.framework.ProxyFactoryBean"&gt;<br />	&lt;property name="proxyInterfaces"&gt;	<br />	&lt;value&gt;net.xmethods.www.sd.CurrencyExchangeService_wsdl.<br />	CurrencyExchangePortType&lt;/value&gt;<br />	&lt;/property&gt;<br />	&lt;property name="target"&gt; <br />		&lt;ref local="CurrencyExchangeService"/&gt; <br />	&lt;/property&gt;<br />	&lt;property name="interceptorNames"&gt;<br />		&lt;list&gt;<br />			&lt;value&gt;WebServicePerformanceMonitorInterceptor&lt;/value&gt;<br />			&lt;value&gt;CacheInterceptor&lt;/value&gt;<br />			&lt;value&gt;FailoverInterceptor&lt;/value&gt;<br />		&lt;/list&gt;<br />	&lt;/property&gt;<br />&lt;/bean&gt;	<br />&lt;bean id="CurrencyExchangeManager"<br />class="test.ws.CurrencyExchangeManagerImpl"&gt;<br />	&lt;property name="stub"&gt;<br />		&lt;ref bean="CurrencyExchangeProxy"/&gt;<br />	&lt;/property&gt;<br />&lt;/bean&gt;<br /></code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>这里我们通过为AOP
的ProxyFactoryBean为 Web Service
Stub创建了一个AOP代理，并且建立了一个Interceptor链。这样在调用Web
Service时，Spring框架会依次调用Interceptor执行。实例执行的顺序图将如图5所示：</p>
		<br />
		<a name="IDAIVMNB">
				<b>图5系统运行顺序图</b>
		</a>
		<br />
		<img src="http://www-128.ibm.com/developerworks/cn/webservices/ws-refactoring/images/image010.jpg" alt="图5系统运行顺序图" border="0" height="209" width="554" />
		<br />
		<p>
				<a name="IDAVVMNB">
						<span class="smalltitle">5.5 Interceptor与JAX-RPC Handler的关系与区别</span>
				</a>
		</p>
		<p>SOAP
Message Handler是JAX-RPC为用户自定义Web Service处理过程提供的一种扩展机制。在处理Web
Service请求/响应过程中，Web Service
引擎会根据部署描述中的定义，按照一定的次序调用Handler的处理代码。用户编写的Handler实现可以截获并修改Web
Service消息和处理流程，从而实现对Web Service引擎处理行为的定制和增强。</p>
		<p>比如，我们可以实现一个服务器端Handler，记录Web Service在受到请求消息和发出响应消息之间的时间间隔来实现对服务器端业务性能的测定。而且我们只需在部署描述中增加Handler声明即可，无需修改任何服务器端代码。</p>
		<p>从
此可以看出，JAX-RPC Handler与我们在上文中所提供的AOP
Interceptor都可以帮助我们的SOA应用程序实现关注分离（Separate
Concern）的目标，在不改变应用代码的同时，增强或改变Web
Service服务访问的功能。虽然我们可以利用它们实现一些类似的功能，但它们具有着不同的特点和适用范围。</p>
		<p>JAX-RPC
Handler是Web Service引擎的扩展机制。如果我们需要实现对SOAP消息进行的修改和处理，加入自定义的SOAP
Header或对消息内容进行加密，Handler是我们的最佳选择。而AOP是针对对象级别的扩展机制，它更适合对应用层逻辑进行操作。</p>
		<p>比
如，我们在上文展示的利用AOP实现的CacheInterceptor，它缓存的是Web
Service调用参数和结果。而我们也可以通过JAX-RPC Handler实现一个面向SOAP消息的实现，它将缓存Web
Service的请求消息和响应消息。这两个实现相比，基于AOP的实现更加简单、直观、快速、对资源消耗也比较小。而面向SOAP消息的实现则更加灵
活，对于不采用RPC方式的Web Service访问也能提供支持。</p>
		<p>所以在具体的实践过程中，开发人员应该根据具体的需求选择合适的技术，也可以将这两种技术结合使用。</p>
		<br />
		<table border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td>
										<img alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" width="100%" />
										<br />
										<img src="http://www.ibm.com/i/c.gif" alt="" border="0" height="6" width="8" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" align="right" cellpadding="0" cellspacing="0">
				<tbody>
						<tr align="right">
								<td>
										<img alt="" src="http://www.ibm.com/i/c.gif" height="4" width="100%" />
										<br />
										<table border="0" cellpadding="0" cellspacing="0">
												<tbody>
														<tr>
																<td valign="middle">
																		<img alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" border="0" height="16" width="16" />
																		<br />
																</td>
																<td align="right" valign="top">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/webservices/ws-refactoring/?S_TACT=105AGX52&amp;S_CMP=techccid#main">
																				<b>回页首</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="IDAAWMNB">
						<span class="atitle">6.总结 </span>
				</a>
		</p>
		<p>"分而治之"的方法是人们解决复杂问题的一种常见做法。而IoC、AOP等技术都体现了这种思想。通过更好的切分程序逻辑，使得程序结构更加良好，更加富有弹性，易于变化。也使得开发人员可以更加专注于业务逻辑本身，而将一部分其他逻辑交给容器和框架进行处理。</p>
		<p>在本文中，我们通过一个Web Service访问的实例，具体描述了SOA应用中所遇到的一系列具体问题，并描述如何利用IoC和AOP等技术进行代码重构，构建更加结构良好、灵活的SOA应用。综上所述，我们可以看到：</p>
		<p>1使用IoC框架来实现对象的生命周期管理、配置管理和依赖管理，可以解除业务逻辑对服务调用的依赖关系；</p>
		<p>2 使用AOP方法来解决Web Service调用中的crosscutting concerns，将为系统增加新的功能而不必更改应用程序。</p>
		<p>3通过IoC和AOP来屏蔽Web Service访问的复杂性，使得开发人员可以更加专注于业务逻辑本身，也使得系统更加稳定和富有弹性。</p>
		<br />
		<br />
		<table border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td>
										<img alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" width="100%" />
										<br />
										<img src="http://www.ibm.com/i/c.gif" alt="" border="0" height="6" width="8" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" align="right" cellpadding="0" cellspacing="0">
				<tbody>
						<tr align="right">
								<td>
										<img alt="" src="http://www.ibm.com/i/c.gif" height="4" width="100%" />
										<br />
										<table border="0" cellpadding="0" cellspacing="0">
												<tbody>
														<tr>
																<td valign="middle">
																		<img alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" border="0" height="16" width="16" />
																		<br />
																</td>
																<td align="right" valign="top">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/webservices/ws-refactoring/?S_TACT=105AGX52&amp;S_CMP=techccid#main">
																				<b>回页首</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<span class="atitle">
						<a name="download">下载</a>
				</span>
		</p>
		<table class="data-table-1" border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<th>描述</th>
								<th>名字</th>
								<th style="text-align: right;">大小</th>
								<th>下载方法</th>
						</tr>
						<tr>
								<td class="tb-row">code sample</td>
								<td nowrap="nowrap">code.zip</td>
								<td style="text-align: right;" nowrap="nowrap">27 KB</td>
								<td nowrap="nowrap">
										<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/webservices/ws-refactoring/code.zip">
												<b>HTTP</b>
										</a>
								</td>
						</tr>
				</tbody>
		</table>
		<table border="0" cellpadding="0" cellspacing="0">
				<tbody>
						<tr valign="top">
								<td colspan="5">
										<img src="http://www.ibm.com/i/c.gif" alt="" border="0" height="12" width="12" />
								</td>
						</tr>
						<tr>
								<td>
										<img src="http://www.ibm.com/i/v14/icons/fw.gif" alt="" height="16" width="16" />
								</td>
								<td>
										<a href="http://www-128.ibm.com/developerworks/cn/whichmethod.html" class="fbox">关于下载方法的信息</a>
								</td>
								<td>
										<img src="http://www.ibm.com/i/c.gif" alt="" height="1" width="50" />
								</td>
								<td>
										<img src="http://www.ibm.com/i/v14/icons/sout.gif" alt="" height="16" width="16" />
								</td>
								<td>
										<a href="http://www.adobe.com/products/acrobat/readstep2.html" class="fbox">Get Adobe® Reader®</a>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<table border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td>
										<img alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" width="100%" />
										<br />
										<img src="http://www.ibm.com/i/c.gif" alt="" border="0" height="6" width="8" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" align="right" cellpadding="0" cellspacing="0">
				<tbody>
						<tr align="right">
								<td>
										<img alt="" src="http://www.ibm.com/i/c.gif" height="4" width="100%" />
										<br />
										<table border="0" cellpadding="0" cellspacing="0">
												<tbody>
														<tr>
																<td valign="middle">
																		<img alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" border="0" height="16" width="16" />
																		<br />
																</td>
																<td align="right" valign="top">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/webservices/ws-refactoring/?S_TACT=105AGX52&amp;S_CMP=techccid#main">
																				<b>回页首</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="resources">
						<span class="atitle">参考资料 </span>
				</a>
		</p>
		<ul>
				<li>JAX-RPC：
<a href="http://java.sun.com/xml/jaxrpc/index.html">http://java.sun.com/xml/jaxrpc/index.html</a><br /><br /></li>
				<li>Spring 参考文档 ：
<a href="http://www.springframework.org/docs/reference/remoting.html">http://www.springframework.org/docs/reference/remoting.html</a><br /><br /></li>
				<li>参考文章：
<a href="http://www-128.ibm.com/developerworks/webservices/library/ws-soa-adventure1/">SOA adventures, Part 1: Ease Web services invocation with dynamic decoupling</a><br /><br /></li>
				<li>关于AOP：
请参考<a href="http://www-128.ibm.com/developerworks/search/searchResults.jsp?searchType=1&amp;searchSite=dWChina&amp;pageLang=zh&amp;langEncoding=UTF8&amp;searchScope=dW&amp;query=AOP">IBM developerWorks</a>上的更多资源。<br /><br /></li>
				<li>J2EE核心模式：
Core J2EE™ Patterns: Best Practices and Design Strategies, Second Edition
By Deepak Alur, John Crupi, Dan Malks<br /></li>
		</ul>
		<br />
		<table border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td>
										<img alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" width="100%" />
										<br />
										<img src="http://www.ibm.com/i/c.gif" alt="" border="0" height="6" width="8" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" align="right" cellpadding="0" cellspacing="0">
				<tbody>
						<tr align="right">
								<td>
										<img alt="" src="http://www.ibm.com/i/c.gif" height="4" width="100%" />
										<br />
										<table border="0" cellpadding="0" cellspacing="0">
												<tbody>
														<tr>
																<td valign="middle">
																		<img alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" border="0" height="16" width="16" />
																		<br />
																</td>
																<td align="right" valign="top">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/webservices/ws-refactoring/?S_TACT=105AGX52&amp;S_CMP=techccid#main">
																				<b>回页首</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="author">
						<span class="atitle">作者简介</span>
				</a>
		</p>
		<table border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td colspan="3">
										<img src="http://www.ibm.com/i/c.gif" alt="" height="5" width="100%" />
								</td>
						</tr>
						<tr align="left" valign="top">
								<td>
										<br />
								</td>
								<td>
										<img src="http://www.ibm.com/i/c.gif" alt="" height="5" width="4" />
								</td>
								<td width="100%">
										<p>易立 IBM 中国软件开发实验室 SOA设计中心 高级软件工程师。</p>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<table border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td colspan="3">
										<img src="http://www.ibm.com/i/c.gif" alt="" height="5" width="100%" />
								</td>
						</tr>
						<tr align="left" valign="top">
								<td>
										<br />
								</td>
								<td>
										<img src="http://www.ibm.com/i/c.gif" alt="" height="5" width="4" />
								</td>
								<td width="100%">
										<p>赵勇 IBM 中国软件开发实验室 SOA设计中心 软件工程师。</p>
								</td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.blogjava.net/alex/aggbug/60552.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/alex/" target="_blank">Alex</a> 2006-07-28 13:29 <a href="http://www.blogjava.net/alex/archive/2006/07/28/60552.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]为什么现在要选择SOA？</title><link>http://www.blogjava.net/alex/archive/2006/07/28/60522.html</link><dc:creator>Alex</dc:creator><author>Alex</author><pubDate>Fri, 28 Jul 2006 03:29:00 GMT</pubDate><guid>http://www.blogjava.net/alex/archive/2006/07/28/60522.html</guid><wfw:comment>http://www.blogjava.net/alex/comments/60522.html</wfw:comment><comments>http://www.blogjava.net/alex/archive/2006/07/28/60522.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/alex/comments/commentRss/60522.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/alex/services/trackbacks/60522.html</trackback:ping><description><![CDATA[key words: SOA<br /><br />come from <a href="http://www.csdn.net/beaeworld/SOA-why.htm">here</a><br /><h1><span style="font-size: 10pt; font-family: ˎ̥; color: rgb(51, 51, 51);" lang="EN-US">2004</span><span style="font-size: 10pt; font-family: 宋体; color: rgb(51, 51, 51);">年</span><span style="font-size: 10pt; font-family: ˎ̥; color: rgb(51, 51, 51);" lang="EN-US">5</span><span style="font-size: 10pt; font-family: 宋体; color: rgb(51, 51, 51);">月</span><span style="font-size: 10pt; font-family: ˎ̥; color: rgb(51, 51, 51);" lang="EN-US">12</span><span style="font-size: 10pt; font-family: 宋体; color: rgb(51, 51, 51);">日</span><span style="font-size: 10pt; font-family: ˎ̥; color: rgb(51, 51, 51);"></span><span style="font-size: 10pt; font-family: 宋体; color: black;">据业内分析，面向服务的架构（</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">SOA</span><span style="font-size: 10pt; font-family: 宋体; color: black;">）的基本概念</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">--</span><span style="font-size: 10pt; font-family: 宋体; color: black;">重用性和互用性</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">--</span><span style="font-size: 10pt; font-family: 宋体; color: black;">已经提出了大约</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">20</span><span style="font-size: 10pt; font-family: 宋体; color: black;">年。那么</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">SOA</span><span style="font-size: 10pt; font-family: 宋体; color: black;">具有哪些新的特色呢？为什么其他技术和标准都惨遭失败，而</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">SOA</span><span style="font-size: 10pt; font-family: 宋体; color: black;">却能够成功呢？</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">BEA</span><span style="font-size: 10pt; font-family: 宋体; color: black;">的首席信息官</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">Rhonda Hocker</span><span style="font-size: 10pt; font-family: 宋体; color: black;">回答了有关</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">SOA</span><span style="font-size: 10pt; font-family: 宋体; color: black;">如何发挥</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">IT</span><span style="font-size: 10pt; font-family: 宋体; color: black;">潜力方面的问题。</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US"><o:p></o:p></span></h1><p class="MsoNormal"><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US"><br /></span><span style="font-size: 10pt; font-family: 宋体; color: rgb(204, 0, 0);">问：</span><span style="font-size: 10pt; font-family: 宋体; color: black;">您认为</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">SOA</span><span style="font-size: 10pt; font-family: 宋体; color: black;">的哪些方面在其成功中起到了至关重要的作用？</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US"><br /><br /></span><span style="font-size: 10pt; font-family: 宋体; color: rgb(204, 0, 0);">答：</span><span style="font-size: 10pt; font-family: 宋体; color: black;">第一点就是灵活性。就长期以来在广大公司中的知名度而言，</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">SOA</span><span style="font-size: 10pt; font-family: 宋体; color: black;">可能名列</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">IT</span><span style="font-size: 10pt; font-family: 宋体; color: black;">架构第一，而内容一直在变化。一个</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">SOA</span><span style="font-size: 10pt; font-family: 宋体; color: black;">实质上就是一套松散耦合的服务。在必要的情况下，每一项服务都可以进行构造和替换，而相关的费用很低。松散耦合甚至还可以让架构适应一些改变，并不像传统的紧耦合架构表现得那么脆弱；在一个</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">SOA</span><span style="font-size: 10pt; font-family: 宋体; color: black;">中，您能够使用一种服务替换另一种服务，无需考虑下列技术：接口问题，它是否在</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">Web</span><span style="font-size: 10pt; font-family: 宋体; color: black;">服务和</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">XML</span><span style="font-size: 10pt; font-family: 宋体; color: black;">的通用标准中已经定义。这就是通过互用性所体现出来的灵活性。灵活性还表现为利用现有资产、遗留应用程序和数据库的能力，通过将他们扩展到</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">SOA</span><span style="font-size: 10pt; font-family: 宋体; color: black;">中，而非进行替换，使其成为整个企业解决方案的组成部分。最终结果就是具备快速高效发展的能力，换句话说，就是按照业务需求</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">"</span><span style="font-size: 10pt; font-family: 宋体; color: black;">有机地</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">"</span><span style="font-size: 10pt; font-family: 宋体; color: black;">进行适应。这就是真正的新特色。</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US"><br /><br /></span><span style="font-size: 10pt; font-family: 宋体; color: black;">第二点就是</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">"</span><span style="font-size: 10pt; font-family: 宋体; color: black;">业务相关性</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">"</span><span style="font-size: 10pt; font-family: 宋体; color: black;">：</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">SOA</span><span style="font-size: 10pt; font-family: 宋体; color: black;">就是最终表现为对业务人员意义重大这一层面上的</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">IT</span><span style="font-size: 10pt; font-family: 宋体; color: black;">架构。如果您也相信</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">IT</span><span style="font-size: 10pt; font-family: 宋体; color: black;">架构的核心问题就是业务和</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">IT</span><span style="font-size: 10pt; font-family: 宋体; color: black;">专家的联盟和协作，那么这就是关键。今天的</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">SOA</span><span style="font-size: 10pt; font-family: 宋体; color: black;">服务能够完成映射为业务流程活动的各部分工作：例如，想起一个命名为</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">"</span><span style="font-size: 10pt; font-family: 宋体; color: black;">更新客户订单状态</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">"</span><span style="font-size: 10pt; font-family: 宋体; color: black;">的服务。这种服务与那些能够参与创造和使用这些服务定义新流程的业务分析人员密切相关，因而能够形成那种服务驱动型的企业。因为</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">Web</span><span style="font-size: 10pt; font-family: 宋体; color: black;">服务已将其大部分技术作了摘要，所以几乎不再需要技术说明。公司和</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">IT</span><span style="font-size: 10pt; font-family: 宋体; color: black;">业能够将关注的重点转移到业务逻辑和通讯上。他们最终共享</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">"</span><span style="font-size: 10pt; font-family: 宋体; color: black;">服务</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">"</span><span style="font-size: 10pt; font-family: 宋体; color: black;">的通用语言。也就是说，是真正的新特色，在</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">IT</span><span style="font-size: 10pt; font-family: 宋体; color: black;">架构的交付中具有深刻的蕴涵。</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US"><br /><br /></span><span style="font-size: 10pt; font-family: 宋体; color: rgb(204, 0, 0);">问：</span><span style="font-size: 10pt; font-family: 宋体; color: black;">您认为什么是</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">SOA</span><span style="font-size: 10pt; font-family: 宋体; color: black;">成功的最大障碍呢？</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US"><br /></span><span style="font-size: 10pt; font-family: 宋体; color: rgb(204, 0, 0);">答：</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">SOA</span><span style="font-size: 10pt; font-family: 宋体; color: black;">是新型</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">IT</span><span style="font-size: 10pt; font-family: 宋体; color: black;">架构的蓝图。由于总是伴随着大的变化发生，因此最大的障碍就是组织，而非技术。主要包括以下几个方面：</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US"><br /><br /></span><span style="font-size: 10pt; font-family: 宋体; color: black;">管理：共享服务是</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">SOA</span><span style="font-size: 10pt; font-family: 宋体; color: black;">方法的核心。这种快速组装应用或编排流程的能力是在一些现有的能被共享的服务的基础上实现的。共享资源需要进行管理。</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US"><br /><br /></span><span style="font-size: 10pt; font-family: 宋体; color: black;">开发文化：切换到</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">SOA</span><span style="font-size: 10pt; font-family: 宋体; color: black;">要求开发风格发生极大的变化。大多数开发人员仍然适应那种将每一个应用程序作为一个独立的问题解决的方式。目前可以重用的代码还非常少。在</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">SOA</span><span style="font-size: 10pt; font-family: 宋体; color: black;">中，开发人员需要编写自己的应用程序，同时还要留意要让自己编写的代码可以重用，不仅包括使用现有代码，还要包括计划在未来的应用程序中重用他们的代码。</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US"><br /><br /></span><span style="font-size: 10pt; font-family: 宋体; color: black;">业务流程架构技能：</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">SOA</span><span style="font-size: 10pt; font-family: 宋体; color: black;">方法让公司和</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">IT</span><span style="font-size: 10pt; font-family: 宋体; color: black;">合作伙伴能够在业务流程的创造中完成更高效率的协同工作。他们的成功将有赖于其实施业务流程架构的技能。也需要他们灵活应对业务流程并且要将自己看作是业务流程架构设计师。</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US"><br /><br /></span><span style="font-size: 10pt; font-family: 宋体; color: black;">这些方面的确都具有极大的挑战性，但是便于管理。最后，那些善于管理，</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">IT</span><span style="font-size: 10pt; font-family: 宋体; color: black;">和业务人员知道如何有效合作，流程和架构技能受到重视的公司将会从自身的</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">SOA</span><span style="font-size: 10pt; font-family: 宋体; color: black;">中得到更多的回报。这几乎是最好的方式，它有助于解决</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">IT </span><span style="font-size: 10pt; font-family: 宋体; color: black;">问题。</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US"><br /><br /></span><span style="font-size: 10pt; font-family: 宋体; color: rgb(204, 0, 0);">问：</span><span style="font-size: 10pt; font-family: 宋体; color: black;">现在的</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">SOA</span><span style="font-size: 10pt; font-family: 宋体; color: black;">与以前的集成</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">/</span><span style="font-size: 10pt; font-family: 宋体; color: black;">连通标准，如</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">CORBA</span><span style="font-size: 10pt; font-family: 宋体; color: black;">有哪些不同之处？</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US"><br /><br /></span><span style="font-size: 10pt; font-family: 宋体; color: rgb(204, 0, 0);">答：</span><span style="font-size: 10pt; font-family: 宋体; color: black;">很好，我将会用案例说明以上我所描述的两个</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">SOA</span><span style="font-size: 10pt; font-family: 宋体; color: black;">有别于其他标准的优点。问题是为什么分布式架构中的</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">CORBA</span><span style="font-size: 10pt; font-family: 宋体; color: black;">和其他方法无法表现出这些优点呢？</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US"><br /></span><span style="font-size: 10pt; font-family: 宋体; color: black;">高度概括性的回答就是：</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">CORBA</span><span style="font-size: 10pt; font-family: 宋体; color: black;">比</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">SOA</span><span style="font-size: 10pt; font-family: 宋体; color: black;">具有更大的技术难度，在其执行过程中需要强大的技能和知识支持。那些技能十分贫乏，如果没有真正的</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">CORBA</span><span style="font-size: 10pt; font-family: 宋体; color: black;">标准将会无济于事。而比较而言，</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">SOA</span><span style="font-size: 10pt; font-family: 宋体; color: black;">简单，基于真正通用的标准。这就确保了构造它们的这些技能是广泛可用的。</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US"><br /><br /></span><span style="font-size: 10pt; font-family: 宋体; color: black;">更为详细的回答请您查看他们的架构方法和原理的基本差别。</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US"><br /><br /></span><span style="font-size: 10pt; font-family: 宋体; color: black;">在一个</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">SOA</span><span style="font-size: 10pt; font-family: 宋体; color: black;">中，分布式资产就是</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">"</span><span style="font-size: 10pt; font-family: 宋体; color: black;">粗粒度</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">"</span><span style="font-size: 10pt; font-family: 宋体; color: black;">服务，它可以完成一些非常有用的功能，如</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">"</span><span style="font-size: 10pt; font-family: 宋体; color: black;">更新客户订单状态</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">"</span><span style="font-size: 10pt; font-family: 宋体; color: black;">。使用</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">CORBA</span><span style="font-size: 10pt; font-family: 宋体; color: black;">，分布式资产就是一些对象，每个对象都拥有自己的属性和方法。例如，订单对象具有</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">"</span><span style="font-size: 10pt; font-family: 宋体; color: black;">状态</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">"</span><span style="font-size: 10pt; font-family: 宋体; color: black;">属性和</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">"</span><span style="font-size: 10pt; font-family: 宋体; color: black;">更新</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">"</span><span style="font-size: 10pt; font-family: 宋体; color: black;">方法。这样对架构设计师而言是相当繁琐的，它需要具有很高水平的知识和技能。在这种细粒度级别之下很难保证一致性。而使用</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">SOA</span><span style="font-size: 10pt; font-family: 宋体; color: black;">，会控制少和动力少，却易于管理。这种方法在技术上并不是非常强大，但在</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">IT</span><span style="font-size: 10pt; font-family: 宋体; color: black;">成功方面的组织和人员角色上却体现出了相当的敏捷度。</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US"><br /><br /></span><span style="font-size: 10pt; font-family: 宋体; color: rgb(204, 0, 0);">问：</span><span style="font-size: 10pt; font-family: 宋体; color: black;">为什么</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">SOA</span><span style="font-size: 10pt; font-family: 宋体; color: black;">会成功而</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">CORBA</span><span style="font-size: 10pt; font-family: 宋体; color: black;">会导致失败呢？</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US"><br /><br /></span><span style="font-size: 10pt; font-family: 宋体; color: rgb(204, 0, 0);">答：</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">SOA</span><span style="font-size: 10pt; font-family: 宋体; color: black;">会成功主要取决于合作伙伴的帮助。就重用效率或企业广泛一致性而言，由中心</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">IT</span><span style="font-size: 10pt; font-family: 宋体; color: black;">组织独立推动的架构都无法在长时间的运行中获得成功。我认为使用</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">SOA</span><span style="font-size: 10pt; font-family: 宋体; color: black;">，我们将会拥有第一个业务合作伙伴帮助推动企业架构的实例。这不是因为他们喜欢架构本身，而是因为他们的支持是基于</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">SOA</span><span style="font-size: 10pt; font-family: 宋体; color: black;">的业务相关性的，很快就可以从结果上看出，开发生命周期改变了它的重点，由原来较长的交付周期应用程序的交付转变成小单元代码</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">--</span><span style="font-size: 10pt; font-family: 宋体; color: black;">服务的交付和集成。持续的结果将使业务合作伙伴效忠于这种方法。</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US"><br /><br /></span><span style="font-size: 10pt; font-family: 宋体; color: rgb(204, 0, 0);">问：</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">Java</span><span style="font-size: 10pt; font-family: 宋体; color: black;">在</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">SOA</span><span style="font-size: 10pt; font-family: 宋体; color: black;">的潜在成功中起到了什么作用？</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US"><br /><br /></span><span style="font-size: 10pt; font-family: 宋体; color: rgb(204, 0, 0);">答：</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">Java</span><span style="font-size: 10pt; font-family: 宋体; color: black;">作为实现服务的最流行的编程标准，是非常重要的。</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">Java</span><span style="font-size: 10pt; font-family: 宋体; color: black;">社区的规模和技能保证大量高质量的技能可以用于构造</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">SOA</span><span style="font-size: 10pt; font-family: 宋体; color: black;">。这就是</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">Java</span><span style="font-size: 10pt; font-family: 宋体; color: black;">实现帮助</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">SOA</span><span style="font-size: 10pt; font-family: 宋体; color: black;">成功的方式。也就是说，</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">Java</span><span style="font-size: 10pt; font-family: 宋体; color: black;">只是实现服务的一种方式。没有一个大的</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">IT</span><span style="font-size: 10pt; font-family: 宋体; color: black;">组织会只运作一个单一的编程标准。有利的方面就是使用</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">SOA</span><span style="font-size: 10pt; font-family: 宋体; color: black;">您不需要一个单一的编程标准。服务范例的定义只能以</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">Web</span><span style="font-size: 10pt; font-family: 宋体; color: black;">服务和</span><span style="font-size: 10pt; font-family: ˎ̥; color: black;" lang="EN-US">XML</span><span style="font-size: 10pt; font-family: 宋体; color: black;">的接口标准识别出这种内在的多相性并设立需求。</span></p><br /><img src ="http://www.blogjava.net/alex/aggbug/60522.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/alex/" target="_blank">Alex</a> 2006-07-28 11:29 <a href="http://www.blogjava.net/alex/archive/2006/07/28/60522.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]为何不让SOA变得简单？</title><link>http://www.blogjava.net/alex/archive/2006/07/28/60511.html</link><dc:creator>Alex</dc:creator><author>Alex</author><pubDate>Fri, 28 Jul 2006 03:03:00 GMT</pubDate><guid>http://www.blogjava.net/alex/archive/2006/07/28/60511.html</guid><wfw:comment>http://www.blogjava.net/alex/comments/60511.html</wfw:comment><comments>http://www.blogjava.net/alex/archive/2006/07/28/60511.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/alex/comments/commentRss/60511.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/alex/services/trackbacks/60511.html</trackback:ping><description><![CDATA[key words:soa <br />转自<a href="http://java.chinaitlab.com/core/353993.html">这里</a><br /><br />最近，SOA成为跨技术平台（特别是J2EE和.Net）软件开发中的热门话题。然而，如果我们比较一下围绕着SOA的宣传和90年代后期EJB和服务件
的宣传，你会发现这没有什么区别。1998年，EJB带领互联网的潮流并推翻了以CORBA的统治和由PB/Oracle
Forms和其他主导的CS架构标准。SOA，作为一种新技术的术语，还不具有那么大的破坏性。SOA只是一种想法/概念和一组构建应用功能的最佳实践。
相反地，J2EE是一套完整地开发技术，可以用来设计所有的东西。<br /><br />　　我对SOA的主要关注在于企业级Java应用通用的问题：复杂性。
次要关注的是SOA通常作为一种解决方案被用来跨越J2EE应用各层，虽然这好像没有什么意义。本文提取出SOA的基本元素并介绍他们。一旦我们理解这
些，就可以理解SOA系统中的更复杂的组件了。最后，我们可以了解一下SOA给J2EE应用带来的实际价值，同时并不增加无用的复杂性。<br />本文分为个部分：首先，提出了我对SOA作为一种标准参考点的定义。其次，检查那些主要的软件工种问题通过SOA可以解决而不是用SOA来检查。再次，会给出基于复杂需求的SOA的建议分类。最后，给出三种主要SOA分类的建议实现。<br /><br /><b><span style="font-size: 16px;">　　SOA是什么？</span></b><br /><br />　　SOA有很多定义。下面是我的定义：<br />　　SOA是宏级别的应用到应用架构级的设计模式：<br />　　1、可选地暴露应用的功能作为一组离散的组件。<br />　　2、使这些组件能被用来构建更复杂的组件和应用。<br />　　3、仅包含基于消息的组件内部通讯。<br /><br />　　我还遗漏了什么呢？还有一些方面，包括：<br />　　1、安全性<br />　　2、事务<br />　　3、状态或无状态会话<br />　　4、消息无数据<br />　　5、 消息特性<br />　　6、 消息协议<br />　　7、 消息内容<br />　　8、  具体技术实现<br /><br />　　这些方面也是重要的，但不是主要的。我的定义提取了SOA的核心规则，但没有抛弃概念本身。<br />注意我在定义中引用了设计模式。我认为这是关键。SOA不是什么新技术，事实上，其最吸引人的一个地方是可以利用现有的技术并使其泛出新的光芒。对我来说，SOA更像是一幅蓝图，一组最佳实践，或者说是一个定义下一代的软件应用应该如何设计和实现的规范。<br /><br /><b><span style="font-size: 16px;">　　基础SOA方法</span></b><br /><br />　　从上面的定义，我们应该可以标识出组成SOA应用的必须提供的软件服务的最小集合。简洁地说，这些服务是：<br /><br />　　1、消息层，允许消息通过特定的协议传输和接收。用SOA的说法，这一层称为企业服务母线或简写为ESB。<br />　　2、一个组件模型，如应用必须遵循的发送和接收来消息母线的消息的最小约定。<br /><br />　　取决于你自己的业务需求，这两种服务可以极度的扩大，但在核心来说，消息层和通用组件模型就代表了SOA。<br /><br />　
　注意，我没有在SOA的定义中包含自动定位和发现服务（在大部分JEE场景中，这是很有杀伤力的）。在UDDI（通用描述/发现/集成协议）后的原始想
法是认为企业最终会使用软件服务（通过一个大的基于元数据搜索服务仓库）来购买和销售。这个美梦至少也得十年后，也许永远不会实现，因为人们是需要做的实
际的业务而不是软件。<br /><br />　　JEE应用不需要自动发现服务，例如登录或支付服务，这些服务应该在初始化时设置。不要误导我，如果这些服务的实现不应该硬编码到应用中，那么你也不需要SOA来解决这些问题了。<br /><br />　　下一节，我们会来考虑一下究竟需要SOA来解决什么，或者他能替代什么。<br /><br /><b><span style="font-size: 16px;">　　为什么要SOA？</span></b><br /><br />　
　最近的两拨企业级软件开发的主浪潮是C/S架构和多层架构。虽然多层架构提供了C/S架构中布署/平台支持/性能/伸缩性上更好的效果，但两者都没有解
决一个关键的企业级计算机领域的软件工程问题：如何重用软件功能。作为软件开发人员和架构师，我们始终没有完全解决软件重用的问题。再往下看，你会看到我
也不认为SOA能解决这个问题。然而，我认为软件重用是SOA出现的最重要原因（至少在JEE应用中是这样）。<br /><br />　　其他SOA使用现有的Jini和风格计算。基于Jini环境的特点如下：<br />　　1、自动发现组件/服务<br />　　2、自愈的<br /><br />　
　然而，这些特性并没有与JEE应用等同的重要性。使用JDBC配置数据库的位置只需要一次。我期望数据库来提供容错和除错功能，而且我不需要JEE应用
来尝试当产品实例当机时自动发现其他的数据库实例。另一方面，对一个有2000个工作站的办公室来说自动发现一个彩色打印机是一件好事，这也是符合
Jini硬件的一个关键好处。<br /><br />　　平等地主，在一个真实的全球网格计算环境中，自动发现和枚举计算资源来解决问题是基础框架的关键部分，但这不是一个JEE环境，那儿硬件预先计算的以便在定义用户数据和服务性能之间平衡。<br /><br />　　我的观点是，SOA对不同的需求需要不同对待。在本文中，我只关心JEE架构方面的SOA，而我认为这意味着功能重用。其他从JEE观点来看SOA的优点还有：<br />　　1、松耦合的组件，这是软件设计中重要的部分<br />　　2、引入ESB作为消息层意味着强制“面向接口编程，而不是实现”<br />　　3、异步消息增加了应用的伸缩性<br /><br />　　让我们通过问三个特定的问题来看一下软件重用中更细节的问题：<br />　　1、为什么重用软件是重要的？<br />　　2、SOA是如何提出解决软件重用问题的？<br />　　3、是否SOA的允诺能够使软件重用应用到现实中？<br /><br />　　首先，软件重用是重要的原因如下：<br />　　1、时间和花费上的效率—能够重用已经的组件来满足陈述的业务需求将节省大量的时间和金钱。<br />　　2、重要的特性包括但不限于如稳定性/性能/可管理性/文档/可配置性。因为一个组件被重用的次数越多，对这个组件的投资也越多，他的优势也越多。<br />　　3、 良好设计的可重用框架无论在哪里被使用都拥有正面的效果，而且你愿意的话可以封装更好的想法来解决通用问题。<br /><br />　
　因此我们需要重用性。那么最简单的方法是什么呢？就是打包软件作为一组良好定义的组件来满足离散的功能需求。然后，如果其他应用需要相同的组件，他就可
以重用了。还有些细节需要考虑，如如何配置，但这些细节已经偏离了主题：重用任何语言编写的代码，那些代码必须被设计成一组离散的组件或重构为集合。<br /><br />　　可以参考我在JavaWorld上的第一篇文章，“节省时间的框架”（2000.9），有更多细节善于JEE项目的软件重用。<br /><br />　
　其次，SOA是如何解决软件重用的问题呢？是通过基于组件模型来构建和引入一个重要的强制约定：组件间的通讯要通过下发到ESB的消息来进行，而这就确
保了松耦合。实际上，最广泛布署的SOA实现—Web services可以通过使消息层技术中性来缝合用不同语言开发的组件。<br /><br />　　最
后，SOA对软件重用的允诺真有实际意义吗？不，我想念如果SOA在1945（大概是和ENIAC同时代吧）被发明的话确实可以解决软件重用的问题。但没
有，现存的大量代码是用不同的开发语言编写的，有COBOL/C/C++http://java.chinaitlab.com/C#和其他语言。这些代
码没有作为离散的组件来编写，因此也没有SOA魔法来解决。事实上，我认为有大量的SOA项目的工作是花费在重构相同的代码库。<br /><br />　　现在，让我们来看一下对于JEE应用SOA可以解决的一些问题。<br /><br /><b><span style="font-size: 16px;">　　SOA缺点</span></b><br /><br />　　SOA缺点包括下面三方面：<br />　　1、 SOA自身的缺点，主要当前还没有成熟的实现<br />　　2、 SOA的复杂性<br />　　3、  厂商对SOA在更广泛的JEE产品和方案中的位置<br /><br />　　那么我们就心批判的眼光来看一下：<br /><br />　　·并没有像JEE规范那样有自己的正式规范。虽然有一个发布的规范，但那个太复杂了并且没有遵循80:20法则（80%的应用需要简单的SOA，只有20%的应用需要更强大而复杂的功能）<br />　　·有状态会话依然存在广泛争议而且现在还没有被SOA的缺省实现（Web services）所解决。而无状态会话已经是完全支持了。<br />　　·由于缺省正式或推荐的规范，Web services已经成为许多人眼里SOA的代名词了，但Web services通常是过于强大了。<br />　　·SOA增加了复杂性。可能你更喜欢硬编码和紧耦合，而不需要XML配置文件来运行简单的应用。<br />　
　·SOA兼容的应用对本身来说没有什么意义。其商业价值来自于能够提供离散的功能块通过SOA被用于其他的应用和模块。例如，如果你对订单的较验规则是
通过JSP页面中的Java代码来实现的，那么你还需要重构代码将其放到服务端对象中以便于SOA调用—但很多厂商并没有提及这一点。<br />　　·在某些情况下，厂商将SOA作为网页应用框架的替代者！我认为，WAF是SOA定义功能中的消费者，只是作为一种补充，而不存在竟争关系。<br />　　· 与厂商提供的相反，一些应用根本不需要SOA而只需要简单使用MVC框架就可以了。这很短视吗？我不这么认为，即使SOA的特性是需要的，在上面的情况下，最重要的部分是用来服务于企业服务总线的良好定义的业务逻辑层，而不是ESB自身。<br /><br />　　虽然我不认为SOA是一颗解决现有和新建应用中问题的银弹，便我相信SOA在他相应的位置上还是有其内在的价值的。现在让我们来看一下在应用中增加有效的SOA解决方案是如何提供体现其商业价值的。<br /><br /><b><span style="font-size: 16px;">　　建议的SOA分类</span></b><br /><br />　
　现在，你应该对我保持事物的简单性的热忱表示感激吧。但我本质上并不是简单论者，我是一个实用主义者。对软件项目来说，我认为实用主义是一方面要平衡项
目的商业和实际价值，另一方面是使用软件设计上的最佳实践。简单的说，就是在我们现有条件下构建我们所能创建的最好的系统。<br /><br />　　一个实用主义的好例子来自于民间的工程历史。在修铁路时常修木桥，而我们知道用铁桥会更好。当铁路公司的股东想使用铁路尽快开工而且初始投资要有限制时，他就是这是最好的工程方案了。是否听起来耳熟？同样的原则可以应用于软件工程。<br /><br />　　根据实用主义的精神，我建议将SOA分为三个级别：简单/中等/复杂，衡量标准是需要满足的业务需求。如果你需要简单的SOA，那么不要浪费时间和金钱在复杂的SOA上。<br /><br /><b>　　级别1：简单的SOA</b><br /><br />　　样例实现：<br />　　1、使用自己的POJO队列实现来发送和接收消息。<br />　　2、带有MDB（消息驱动Bean）的JMS队列/主题作为消息的消费者。<br /><br />　　这里涵盖的关键SOA概念有：<br />　　1、企业服务总线<br />　　2、生产者/消费者的组件模型。<br /><br /><p align="center"><img onmouseover="javascript:imgShowTip(this);" style="display: inline; width: 430px; height: 305px;" onclick="javascript:imgClick(this);" alt="resized image" src="http://java.chinaitlab.com/UploadFiles_8734/200602/20060221112516129.jpg" onload="javascript:imgLoad(this);" resized="1" border="0" height="354" width="600" /></p><br />　　Figure 1. Schematic illustrating the core components of the simple SOA. Click on thumbnail to view full-sized image.<br /><br /><b>　　级别2：中等的SOA</b><br /><br />　　样例实现：<br />　　1、带有MDB的JMS队列/主题作为消息的消费者，并附加其他特性如安全性/事务/JMS元数据属性等<br />　　2、 Web services，例如Apache Axis<br /><br />　　这里涵盖的关键SOA概念在包含简单SOA外还有：<br />　　1、用来增加健壮性和可靠性的错误/重试队列。<br />　　2、引入XML作为消息的有效负载内容来代替序列化Java对象，从而支持其他技术如.Net<br /><br /><p align="center"><img onmouseover="javascript:imgShowTip(this);" style="display: inline; width: 450px; height: 288px;" onclick="javascript:imgClick(this);" alt="resized image" src="http://java.chinaitlab.com/UploadFiles_8734/200602/20060221112519953.jpg" onload="javascript:imgLoad(this);" resized="1" border="0" height="353" width="600" /></p><br />　
　Figure 2. Schematic illustrating the core components of the
medium-complexity SOA. Click on thumbnail to view full-sized image.<br /><br /><b>　　级别3：复杂的SOA</b><br /><br />　　样例实现：<br />　　1、带有MDB的JMS队列/主题作为消息的消费者，并附加其他特性如安全性/事务/JMS元数据属性等<br />　　2、Web services<br />　　3、厂商/标准相关的SOA兼容工具包（如专门的金融服务）<br /><br />　　这里涵盖的关键SOA概念在包含中等SOA外还有：<br />　　1、良好定义而且严格的组件模型（例如Java业务集成/服务组件架构及其他）<br />　　2、增强的厂商支持，如可插拔的新生产者/消费者组件创建<br />　　3、 详细枚举特定SOA实现上可用服务的组件注册表。<br /><br /><p align="center"><img onmouseover="javascript:imgShowTip(this);" style="display: inline; width: 450px; height: 293px;" onclick="javascript:imgClick(this);" alt="resized image" src="http://java.chinaitlab.com/UploadFiles_8734/200602/20060221112519464.jpg" onload="javascript:imgLoad(this);" resized="1" border="0" height="361" width="600" /></p><p><br />　　Figure 3. Schematic illustrating the core components of the complex SOA. Click on thumbnail to view full-sized image.<br /><br /><b><span style="font-size: 16px;">　　小结</span></b><br /><br />　
　目前SOA是作为一种架构体现，也将会成为与C/S或多层架构一样存在。但是，他目前还是不够成熟而且只是作为厂商利用的工具。我对SOA的建议是，从
简单的做起并保持SOA尽可能的简单。不要将SOA与Web
services等同起来，也不要强制使用SOA的设计模式在JEE应用的各层上，告别是网页层。<br /><br />　　那么我会为大多数JEE应用推荐哪
一个SOA实现呢？级别2上的SOA实现如带有MDB的JMS队列作为消费者，而POJO或无状态的会话Bean作为消息生产者。当然，如果你确信你需要
集成非Java应用,那么考虑一下Web
services实现。还要考虑你现在采用的解决方案在以后要有足够的扩展空间。虽然预测多久通常都有争议的，但我还是建议最远不超过36个月。如果你预
见到那个时间段内有额外的SOA需求，那么现在就来构建吧。<br /><br /><b>　　关于作者</b><br /><br />　　Humphrey Sheil是英国服务业企业级应用供应商CedaropenAccounts的首席技术架构师。特别擅长于集成领域。拥有爱尔兰都柏林大学的计算机科学硕士学位。点击这里进入他的博客。<br /><br /><b>　　资源</b><br /><br />　　·Jini技术，最早的SOA实现之一:http://www.jini.org <br />　　·JEE规范:http://java.sun.com/j2ee/download.html#platformspec <br />　　·学习.Net的的入门点：http://msdn2.microsoft.com/en-us/library/ms310245(en-us,MSDN.10).aspx <br />　　·http://www.uddi.org UDDI协议<br />　　·创建SOA的准备：http://weblog.infoworld.com/techwatch/archives/004644.html <br />　
　·Java业务集成，用来为Java应用（特别指基于SOA的应用）定义组件模型的规范。这更正规些，因此允许厂商根据标准提供工具和框架以实现最终的
交互性。目前许多失败就是因为缺少这些支持：http://www.jcp.org/en/jsr/detail?id=208 <br />　　·http://ws.apache.org/axis/ 开源的JEE网页服务实现- Apache Axis </p><p>　　版权声明：任何获得Matrix授权的网站，转载时请务必保留以下作者信息和链接<br />　　原文:http://www.javaworld.com/<br />　　译文:http://www.matrix.org.cn/</p><img src ="http://www.blogjava.net/alex/aggbug/60511.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/alex/" target="_blank">Alex</a> 2006-07-28 11:03 <a href="http://www.blogjava.net/alex/archive/2006/07/28/60511.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>