1.Spring中,HTTPInvoker(HTTP调用器)是通过基于HTTP协议的分布式远程调用解决方案,和java RMI一样,HTTP调用器也需要使用java的对象序列化机制完成客户端和服务器端的通信。HTTP调用器的远程调用工作原理如下:

(1).客户端:

a.向服务器发送远程调用请求:

远程调用信息——>封装为远程调用对象——>序列化写入到远程调用HTTP请求中——>向服务器端发送。

b.接收服务器端返回的远程调用结果:

服务器端返回的远程调用结果HTTP响应——>反序列化为远程调用结果对象。

(2).服务器端:

a.接收客户端发送的远程调用请求:

客户端发送的远程调用HTTP请求——>反序列化为远程调用对象——>调用服务器端目标对象的目标方法处理。

b.向客户端返回远程调用结果:

服务器端目标对象方法的处理结果——>序列化写入远程调用结果HTTP响应中——>返回给客户端。

接下来我们将从客户端和服务器端分别分析HTTP调用器远程调用的具体实现。

2.HTTP调用器客户端配置:

使用HTTP调用器之前,首先需要对客户端其进行如下的配置:


[xhtml] view plain copy
  1. <!--客户端HTTP调用器代理-->

  2. <beanid=”proxy” class=”org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean”>

  3. <propertyname=”serviceUrl”>

  4. <value>http://yourhost:8080/远程调用URL</value>

  5. </property>

  6. <propertyname=”serviceInterface”>

  7. <value>远程调用服务接口全路径</value>

  8. </property>

  9. </bean>

  10. <beanid=”客户端bean” class=”客户端Bean全路径”>

  11. <propertyname=”remoteService”>

  12. <refbean=”proxy”/>

  13. </property>

  14. </bean>

HTTP调用器客户端代理HttpInvokerProxyFactoryBean中封装远程调用服务URL和服务接口,客户端程序通过HTTP调用代理可以调用实现了指定接口的目标服务端对象。

3.HttpInvokerProxyFactoryBean创建远程调用代理对象:

HTTP调用器客户端代理HttpInvokerProxyFactoryBean是一个实现了Spring FactoryBean接口的IoC容器,其作用是对远程服务客户端封装,源码如下:


[java] view plain copy
  1. publicclass HttpInvokerProxyFactoryBean extends HttpInvokerClientInterceptor implements FactoryBean<Object> {  

  2. //远程对象的代理

  3. private Object serviceProxy;  

  4. //在IoC容器注入完成之后调用

  5. publicvoid afterPropertiesSet() {  

  6. //调用父类容器的回调方法

  7. super.afterPropertiesSet();  

  8. //getServiceInterface()方法用于获取配置的远程调用接口

  9. if (getServiceInterface() == null) {  

  10. thrownew IllegalArgumentException("Property 'serviceInterface' is required");  

  11.        }  

  12. //使用ProxyFactory代理工厂生成远程代理对象,注意第二个参数this,因为

  13. //HttpInvokerProxyFactoryBean继承了HttpInvokerClientInterceptor,

  14. //所以代理对象的拦截器设置为HttpInvokerClientInterceptor

  15. this.serviceProxy = new ProxyFactory(getServiceInterface(), this).getProxy(getBeanClassLoader());  

  16.    }  

  17. //向IoC容器索取被管理对象的方法,获取产生的远程调用代理对象

  18. public Object getObject() {  

  19. returnthis.serviceProxy;  

  20.    }  

  21. //获取对象类型,返回配置的远程调用接口

  22. public Class<?> getObjectType() {  

  23. return getServiceInterface();  

  24.    }  

  25. //是否是单态类型,默认Spring IoC容器产生的都是单态类型

  26. publicboolean isSingleton() {  

  27. returntrue;  

  28.    }  

  29. }  

通过上面对HttpInvokerProxyFactoryBean源码的分析我们看到,当通过getObject方法向Spring IoC容器索取远程调用对象时,触发afterPropertiesSet回调方法,创建远程调用的代理对象,最后将该远程调用代理对象返回。在创建远程调用代理对象时,使用其父类HttpInvokerClientInterceptor作为远程调用代理对象的拦截器,该拦截器将拦截对代理对象的方法调用。下面我们分析HttpInvokerClientInterceptor代理拦截器对代理对象的方法拦截处理。

4.HttpInvokerClientInterceptor拦截对远程调用代理的方法调用:

当客户端通过HTTP请求调用远程调用代理的方法时,将会触发HttpInvokerClientInterceptor拦截器的invoke方法对当前的请求进行封装处理,将客户端的java对象序列化传输到服务器端,在远程服务器端执行完请求之后,又将处理结果java对象序列化返回给客户端。其源码如下:


[java] view plain copy
  1. publicclass HttpInvokerClientInterceptor extends RemoteInvocationBasedAccessor  

  2. implements MethodInterceptor, HttpInvokerClientConfiguration {  

  3. private String codebaseUrl;  

  4. //HTTP调用请求执行器

  5. private HttpInvokerRequestExecutor httpInvokerRequestExecutor;  

  6. publicvoid setCodebaseUrl(String codebaseUrl) {  

  7. this.codebaseUrl = codebaseUrl;  

  8.    }  

  9. public String getCodebaseUrl() {  

  10. returnthis.codebaseUrl;  

  11.    }  

  12. publicvoid setHttpInvokerRequestExecutor(HttpInvokerRequestExecutor httpInvokerRequestExecutor) {  

  13. this.httpInvokerRequestExecutor = httpInvokerRequestExecutor;  

  14.    }  

  15. //获取HTTP调用请求执行器,如果HTTP调用请求执行器没有设置,则使用

  16. //SimpleHttpInvokerRequestExecutor作为HTTP调用请求执行器

  17. public HttpInvokerRequestExecutor getHttpInvokerRequestExecutor() {  

  18. if (this.httpInvokerRequestExecutor == null) {  

  19.            SimpleHttpInvokerRequestExecutor executor = new SimpleHttpInvokerRequestExecutor();  

  20.            executor.setBeanClassLoader(getBeanClassLoader());  

  21. this.httpInvokerRequestExecutor = executor;  

  22.        }  

  23. returnthis.httpInvokerRequestExecutor;  

  24.    }  

  25. //IoC容器初始化完成回调方法

  26. publicvoid afterPropertiesSet() {  

  27. //调用父类的初始化回调方法

  28. super.afterPropertiesSet();  

  29. //获取HTTP调用请求执行器

  30.        getHttpInvokerRequestExecutor();  

  31.    }  

  32. //拦截器代理对象方法调用入口,拦截器将客户端对远程调用代理的调用封装为

  33. //MethodInvocation对象。

  34. public Object invoke(MethodInvocation methodInvocation) throws Throwable {  

  35. if (AopUtils.isToStringMethod(methodInvocation.getMethod())) {  

  36. return"HTTP invoker proxy for service URL [" + getServiceUrl() + "]";  

  37.        }  

  38. //创建远程调用对象,封装了远程调用

  39.        RemoteInvocation invocation = createRemoteInvocation(methodInvocation);  

  40. //远程调用结果

  41.        RemoteInvocationResult result = null;  

  42. try {  

  43. //远程调用入口

  44.            result = executeRequest(invocation, methodInvocation);  

  45.        }  

  46. catch (Throwable ex) {  

  47. throw convertHttpInvokerAccessException(ex);  

  48.        }  

  49. try {  

  50. //返回远程调用结果

  51. return recreateRemoteInvocationResult(result);  

  52.        }  

  53. catch (Throwable ex) {  

  54. if (result.hasInvocationTargetException()) {  

  55. throw ex;  

  56.            }  

  57. else {  

  58. thrownew RemoteInvocationFailureException("Invocation of method [" + methodInvocation.getMethod() +  

  59. "] failed in HTTP invoker remote service at [" + getServiceUrl() + "]", ex);  

  60.            }  

  61.        }  

  62.    }  

  63. //执行远程调用入口

  64. protected RemoteInvocationResult executeRequest(  

  65.            RemoteInvocation invocation, MethodInvocation originalInvocation) throws Exception {  

  66. return executeRequest(invocation);  

  67.    }  

  68. //通过HTTP调用请求执行器执行远程调用

  69. protected RemoteInvocationResult executeRequest(RemoteInvocation invocation) throws Exception {  

  70. return getHttpInvokerRequestExecutor().executeRequest(this, invocation);  

  71.    }  

  72. //将远程调用异常转换成Spring异常

  73. protected RemoteAccessException convertHttpInvokerAccessException(Throwable ex) {  

  74. if (ex instanceof ConnectException) {  

  75. thrownew RemoteConnectFailureException(  

  76. "Could not connect to HTTP invoker remote service at [" + getServiceUrl() + "]", ex);  

  77.        }  

  78. elseif (ex instanceof ClassNotFoundException || ex instanceof NoClassDefFoundError ||  

  79.                ex instanceof InvalidClassException) {  

  80. thrownew RemoteAccessException(  

  81. "Could not deserialize result from HTTP invoker remote service [" + getServiceUrl() + "]", ex);  

  82.        }  

  83. else {  

  84. thrownew RemoteAccessException(  

  85. "Could not access HTTP invoker remote service at [" + getServiceUrl() + "]", ex);  

  86.        }  

  87.    }  

  88. }  

通过上面对HttpInvokerClientInterceptor拦截器的源码分析,我们可以看出,拦截器将客户端对远程调用的HTTP请求封装成了MethodInvocation对象,拦截器的在调用远程调用的代理对象时,又将方法调用封装成了RemoteInvocation远程调用,RemoteInvocation数据对象中封装了调用的具体信息,如方法名、方法参数以及参数类型等。

真正执行远程调用的是HTTP调用请求执行器SimpleHttpInvokerRequestExecutor,下面我们继续分析SimpleHttpInvokerRequestExecutor远程调用的具体过程。

5.SimpleHttpInvokerRequestExecutor远程调用:

SimpleHttpInvokerRequestExecutor封装了基于HTTP协议的远程调用过程,具体源码如下:


[java] view plain copy
  1. publicclass SimpleHttpInvokerRequestExecutor extends AbstractHttpInvokerRequestExecutor {  

  2. //HTTP调用请求执行器真正进行远程调用的方法,该方法有其父类//AbstractHttpInvokerRequestExecutor的executeRequest方法调用

  3. protected RemoteInvocationResult doExecuteRequest(  

  4.            HttpInvokerClientConfiguration config, ByteArrayOutputStream baos)  

  5. throws IOException, ClassNotFoundException {  

  6. //打开一个标准的J2SE HttpURLConnection

  7.        HttpURLConnection con = openConnection(config);  

  8. //准备连接

  9.        prepareConnection(con, baos.size());  

  10. //远程调用被封装成了RemoteInvocation对象,它通过序列化被写到对应的//HttpURLConnection中

  11.        writeRequestBody(config, con, baos);  

  12. //获取远程调用的结果,校验返回的结果

  13.        validateResponse(config, con);  

  14.        InputStream responseBody = readResponseBody(config, con);  

  15. //将远程调用结果转换成RemoteInvocationResult返回

  16. return readRemoteInvocationResult(responseBody, config.getCodebaseUrl());  

  17.    }  

  18. //打开一个HttpURLConnection

  19. protected HttpURLConnection openConnection(HttpInvokerClientConfiguration config) throws IOException {  

  20. //getServiceUrl()方法获取配置的远程调用URL,打开一个URL连接

  21.        URLConnection con = new URL(config.getServiceUrl()).openConnection();  

  22. if (!(con instanceof HttpURLConnection)) {  

  23. thrownew IOException("Service URL [" + config.getServiceUrl() + "] is not an HTTP URL");  

  24.        }  

  25. return (HttpURLConnection) con;  

  26.    }  

  27. //准备HTTP请求连接

  28. protectedvoid prepareConnection(HttpURLConnection con, int contentLength) throws IOException {  

  29.        con.setDoOutput(true);  

  30. //HTTP调用器只支持POST请求方法

  31.        con.setRequestMethod(HTTP_METHOD_POST);  

  32. //设置HTTP请求头内容类型,设置为:application/x-java-serialized-object

  33.        con.setRequestProperty(HTTP_HEADER_CONTENT_TYPE, getContentType());  

  34. //设置HTTP请求头内容长度

  35.        con.setRequestProperty(HTTP_HEADER_CONTENT_LENGTH, Integer.toString(contentLength));  

  36.        LocaleContext locale = LocaleContextHolder.getLocaleContext();  

  37. //设置HTTP请求的Locale

  38. if (locale != null) {  

  39.            con.setRequestProperty(HTTP_HEADER_ACCEPT_LANGUAGE, StringUtils.toLanguageTag(locale.getLocale()));  

  40.        }  

  41. //设置HTTP请求压缩方式

  42. if (isAcceptGzipEncoding()) {  

  43.            con.setRequestProperty(HTTP_HEADER_ACCEPT_ENCODING, ENCODING_GZIP);  

  44.        }  

  45.    }  

  46. //把序列化对象输出到HTTP请求体中

  47. protectedvoid writeRequestBody(  

  48.            HttpInvokerClientConfiguration config, HttpURLConnection con, ByteArrayOutputStream baos)  

  49. throws IOException {  

  50.        baos.writeTo(con.getOutputStream());  

  51.    }  

  52. //校验远程调用的HTTP响应

  53. protectedvoid validateResponse(HttpInvokerClientConfiguration config, HttpURLConnection con)  

  54. throws IOException {  

  55. //如果HTTP响应状态码大于等于300,则证明调用发生错误

  56. if (con.getResponseCode() >= 300) {  

  57. thrownew IOException(  

  58. "Did not receive successful HTTP response: status code = " + con.getResponseCode() +  

  59. ", status message = [" + con.getResponseMessage() + "]");  

  60.        }  

  61.    }  

  62. //提取远程调用结果的HTTP响应信息

  63. protected InputStream readResponseBody(HttpInvokerClientConfiguration config, HttpURLConnection con)  

  64. throws IOException {  

  65. //如果响应信息是Gzip压缩的,则需要先解压

  66. if (isGzipResponse(con)) {  

  67. returnnew GZIPInputStream(con.getInputStream());  

  68.        }  

  69. //正常的HTTP响应

  70. else {  

  71. return con.getInputStream();  

  72.        }  

  73.    }  

  74. //是否是Gzip格式压缩

  75. protectedboolean isGzipResponse(HttpURLConnection con) {  

  76. //获取HTTP响应头信息中的压缩方式

  77.        String encodingHeader = con.getHeaderField(HTTP_HEADER_CONTENT_ENCODING);  

  78. return (encodingHeader != null && encodingHeader.toLowerCase().indexOf(ENCODING_GZIP) != -1);  

  79.    }  

  80. }  

通过对SimpleHttpInvokerRequestExecutor的分析,我们看到,HTTP调用请求执行器的处理逻辑是:首先,打开指定URLHTTP连接,设置连接属性。其次,将封装请求的RemoteInvocation对象序列化到请求体中,请HTTP请求发送到服务器端。最后,从服务器端的HTTP响应中读取输入流,并将响应结果转换成RemoteInvocationResult

将远程调用的HTTP响应转换为RemoteInvocationResult是由AbstractHttpInvokerRequestExecutorreadRemoteInvocationResult方法实现,下面我们将分析其将HTTP响应结果转换成RemoteInvocationResult的实现。

6.AbstractHttpInvokerRequestExecutor其将HTTP响应结果转换成RemoteInvocationResult

AbstractHttpInvokerRequestExecutor中处理远程调用结果,并HTTP响应转换为RemoteInvocationResult的主要方法如下:


[java] view plain copy
  1. //从HTTP响应中读取远程调用结果入口方法

  2. protected RemoteInvocationResult readRemoteInvocationResult(InputStream is, String codebaseUrl)  

  3. throws IOException, ClassNotFoundException {  

  4. //根据给定的输入流和类创建对象输入流

  5.        ObjectInputStream ois = createObjectInputStream(decorateInputStream(is), codebaseUrl);  

  6. try {  

  7. //从对象输入流中读取远程调用结果

  8. return doReadRemoteInvocationResult(ois);  

  9.        }  

  10. finally {  

  11.            ois.close();  

  12.        }  

  13.    }  

  14. //从对象输入流中读取远程调用结果

  15. protected RemoteInvocationResult doReadRemoteInvocationResult(ObjectInputStream ois)  

  16. throws IOException, ClassNotFoundException {  

  17. //获取对象输入流中的对象

  18.        Object obj = ois.readObject();  

  19. if (!(obj instanceof RemoteInvocationResult)) {  

  20. thrownew RemoteException("Deserialized object needs to be assignable to type [" +  

  21.                    RemoteInvocationResult.class.getName() + "]: " + obj);  

  22.        }  

  23. //将获取到的对象封装为RemoteInvocationResult

  24. return (RemoteInvocationResult) obj;  

  25.    }  

7.HTTP调用器的服务器端配置:

HTTP调用器客户端类似,服务器端也需要进行如下的配置:


[xhtml] view plain copy
  1. <beanname=”/客户端配置的远程调用URL” class=”org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter”>

  2. <propertyname=”service”>

  3. <refbean=”服务器端实现bean”/>

  4. </property>

  5. <propertyname=”serviceInterface”>

  6. <value>远程调用服务接口全路径</value>

  7. </property>

  8. </property>

通过对服务器端配置的例子,我们可以看出,真正处理远程调用的服务器端实现是由service属性中指定的服务器端bean提供的,HttpInvokerServiceExporter将远程调用服务接口和服务实现类进行封装,主要提HTTP协议封装和java对象序列化功能。

SpringHttpInvokerServiceExporter是与SpringMVC结合在一起的,它本质上是Spring MVC的一个Controller,客户端发来的远程调用HTTP请求有Spring MVC的中央控制器DispatcherServlet转发到指定URLHttpInvokerServiceExporter上。

8.HttpInvokerServiceExporter导出和执行远程调用服务:

HttpInvokerServiceExporter响应客户端发送的远程调用HTTP请求,它从HTTP请求中读取远程调用并将其反序列化为RemoteInvocation对象,然后调用目标服务对象的目标方法完成远程调用服务,当服务执行完成之后,通过HTTP响应把执行结果对象序列化输出到客户端。器源码如下:


[java] view plain copy
  1. publicclass HttpInvokerServiceExporter extends RemoteInvocationSerializingExporter implements HttpRequestHandler {  

  2. //处理客户端发来的远程调用HTTP请求

  3. publicvoid handleRequest(HttpServletRequest request, HttpServletResponse response)  

  4. throws ServletException, IOException {  

  5. try {  

  6. //从HTTP请求中反序列化出RemoteInvocation远程调用对象

  7.            RemoteInvocation invocation = readRemoteInvocation(request);  

  8. //调用目标服务对象,完成远程调用请求,并创建调用结果

  9.            RemoteInvocationResult result = invokeAndCreateResult(invocation, getProxy());  

  10. //将调用结果写到HTTP响应中

  11.            writeRemoteInvocationResult(request, response, result);  

  12.        }  

  13. catch (ClassNotFoundException ex) {  

  14. thrownew NestedServletException("Class not found during deserialization", ex);  

  15.        }  

  16.    }  

  17. //从HTTP请求中读取RemoteInvocation远程调用对象入口方法

  18. protected RemoteInvocation readRemoteInvocation(HttpServletRequest request) throws IOException, ClassNotFoundException {  

  19. //将从HTTP请求中读取远程调用对象

  20. return readRemoteInvocation(request, request.getInputStream());  

  21.    }  

  22. //从HTTP请求中读取远程调用对象

  23. protected RemoteInvocation readRemoteInvocation(HttpServletRequest request, InputStream is) throws IOException, ClassNotFoundException {  

  24. //根据HTTP请求输入流创建对象输入流

  25.        ObjectInputStream ois = createObjectInputStream(decorateInputStream(request, is));  

  26. try {  

  27. //从对象输入流中读取远程调用对象

  28. return doReadRemoteInvocation(ois);  

  29.        }  

  30. finally {  

  31.            ois.close();  

  32.        }  

  33.    }  

  34. //获取HTTP请求输入流

  35. protected InputStream decorateInputStream(HttpServletRequest request, InputStream is) throws IOException {  

  36. return is;  

  37.    }  

  38. //将远程调用执行结果写到HTTP响应中

  39. protectedvoid writeRemoteInvocationResult(  

  40.            HttpServletRequest request, HttpServletResponse response, RemoteInvocationResult result) throws IOException {  

  41. //设置HTTP响应的内容类型为:application/x-java-serialized-object

  42.        response.setContentType(getContentType());  

  43. //将远程调用结果写到HTTP响应中

  44.        writeRemoteInvocationResult(request, response, result, response.getOutputStream());  

  45.    }  

  46. //将远程调用执行结果写入HTTP响应中

  47. protectedvoid writeRemoteInvocationResult(  

  48.            HttpServletRequest request, HttpServletResponse response, RemoteInvocationResult result, OutputStream os)  

  49. throws IOException {  

  50. //获取HTTP响应对象输出流

  51.        ObjectOutputStream oos = createObjectOutputStream(decorateOutputStream(request, response, os));  

  52. try {  

  53. //将远程调用执行结果写到HTTP响应对象输出流中

  54.            doWriteRemoteInvocationResult(result, oos);  

  55.        }  

  56. finally {  

  57.            oos.close();  

  58.        }  

  59.    }  

  60. //获取HTTP响应对象输入流

  61. protected OutputStream decorateOutputStream(  

  62.            HttpServletRequest request, HttpServletResponse response, OutputStream os) throws IOException {  

  63. return os;  

  64.    }  

  65. }  

通过对HttpInvokerServiceExporter的源码分析,我们可以看出,真正执行远程对象调用的是RemoteInvocationResultresult = invokeAndCreateResult(invocation, getProxy());它调用了RemoteInvocationBasedExporterinvokeAndCreateResult方法调用远程目标对象方法,并创建远程调用执行结果,下面我们继续分析执行服务器端远程调用目标对象方法的实现。

9.RemoteInvocationBasedExporter调用服务器目标对象:

RemoteInvocationBasedExporterinvokeAndCreateResult方法调用服务器目标对象方法,RemoteInvocationBasedExporter源码如下:


[java] view plain copy
  1. publicabstractclass RemoteInvocationBasedExporter extends RemoteExporter {  

  2. //远程调用执行器

  3. private RemoteInvocationExecutor remoteInvocationExecutor = new DefaultRemoteInvocationExecutor();  

  4. public RemoteInvocationExecutor getRemoteInvocationExecutor() {  

  5. returnthis.remoteInvocationExecutor;  

  6.    }  

  7. protected RemoteInvocationResult invokeAndCreateResult(RemoteInvocation invocation, Object targetObject) {  

  8. try {  

  9. //调用服务器端目标对象的方法

  10.            Object value = invoke(invocation, targetObject);  

  11. //根据执行结果创建RemoteInvocationResult

  12. returnnew RemoteInvocationResult(value);  

  13.        }  

  14. catch (Throwable ex) {  

  15. returnnew RemoteInvocationResult(ex);  

  16.        }  

  17.    }  

  18. //调用目标对象的方法

  19. protected Object invoke(RemoteInvocation invocation, Object targetObject)  

  20. throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {  

  21. if (logger.isTraceEnabled()) {  

  22.            logger.trace("Executing " + invocation);  

  23.        }  

  24. try {  

  25. //获取远程调用执行器,由远程调用执行器调用目标对象的方法,即通过

  26. //DefaultRemoteInvocationExecutor了调用目标对象的方法

  27. return getRemoteInvocationExecutor().invoke(invocation, targetObject);  

  28.        }  

  29. catch (NoSuchMethodException ex) {  

  30. if (logger.isDebugEnabled()) {  

  31.                logger.warn("Could not find target method for " + invocation, ex);  

  32.            }  

  33. throw ex;  

  34.        }  

  35. catch (IllegalAccessException ex) {  

  36. if (logger.isDebugEnabled()) {  

  37.                logger.warn("Could not access target method for " + invocation, ex);  

  38.            }  

  39. throw ex;  

  40.        }  

  41. catch (InvocationTargetException ex) {  

  42. if (logger.isDebugEnabled()) {  

  43.                logger.debug("Target method failed for " + invocation, ex.getTargetException());  

  44.            }  

  45. throw ex;  

  46.        }  

  47.    }  

  48. }  

通过上面对RemoteInvocationBasedExporter源码分析我们看到,真正调用目标对象的是DefaultRemoteInvocationExecutorinvoke方法,下面我们继续分析DefaultRemoteInvocationExecutor调用目标对象方法的实现。

10.DefaultRemoteInvocationExecutor调用目标对象的方法实现远程调用:

DefaultRemoteInvocationExecutor用于调用目标对象的指定方法实现远程对象调用服务,其源码如下:


[java] view plain copy
  1. publicclass DefaultRemoteInvocationExecutor implements RemoteInvocationExecutor {  

  2. //调用目标对象的方法

  3. public Object invoke(RemoteInvocation invocation, Object targetObject)  

  4. throws NoSuchMethodException, IllegalAccessException, InvocationTargetException{  

  5.        Assert.notNull(invocation, "RemoteInvocation must not be null");  

  6.        Assert.notNull(targetObject, "Target object must not be null");  

  7. //调用RemoteInvocation的invoke方法

  8. return invocation.invoke(targetObject);  

  9.    }  

  10. }  

  11. RemoteInvocation的invoke方法源码如下:  

  12. public Object invoke(Object targetObject)  

  13. throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {  

  14. //获取远程调用对象的方法名称和参数类型

  15.        Method method = targetObject.getClass().getMethod(this.methodName, this.parameterTypes);  

  16. //利用JDK反射机制,调用目标对象指定参数的方法

  17. return method.invoke(targetObject, this.arguments);  

  18.    }