Spring框架学习【Spring RMI实现远程调用】

1.Spring除了使用基于HTTP协议的远程调用方案,还为开发者提供了基于RMI机制的远程调用方法,RMI远程调用网络通信实现是基于TCP/IP协议完成的,而不是通过HTTP协议。

在Spring RMI实现中,集成了标准的RMI-JRIM解决方案,该方案是java虚拟机实现的一部分,它使用java序列化来完成对象的传输,是一个java到java环境的分布式处理技术,不涉及异构平台的处理。

2.RMI客户端配置:

和基于HTTP协议的远程调用类似,RMI远程调用客户端也需要进行类似如下的配置:

[java] view plaincopyprint?
  1. <bean id=”rmiProxy” class=”org.springframework.remoting.rmi.RmiProxyFactoryBean”>  
  2.     <property name=”serviceUrl”>  
  3.         <value>rmi://hostAddress:1099/serviceUrl</value>   
  4.     </property>  
  5.     <property name=”serviceInterface”>  
  6.         <value>远程调用接口</value>  
  7.     </property>  
  8. </bean>  
  9. <bean id=”rmiClient” class=”RMI远程调用客户端类全路径”>  
  10.     <property name=”serviceInterface”>  
  11.         <ref bean=”rmiProxy”/>  
  12.     </property>  
  13. </bean>  

注意:上面的配置中serviceUrl必须和服务端的远程调用提供者的id一致,另外,serviceUrl中使用的是rmi协议,默认端口是1099.

3.RmiProxyFactoryBean

RmiProxyFactoryBean的主要功能是对RMI客户端封装,生成代理对象,查询得到RMI的stub对象,并通过这个stub对象发起相应的RMI远程调用请求。其源码如下:

[java] view plaincopyprint?
  1. public class RmiProxyFactoryBean extends RmiClientInterceptor implements FactoryBean<Object>, BeanClassLoaderAware {  
  2.     //远程调用代理对象   
  3.     private Object serviceProxy;  
  4. //Spring IoC容器完成依赖注入后的回调方法   
  5.     public void afterPropertiesSet() {  
  6.         //调用父类RmiClientInterceptor的回调方法   
  7.         super.afterPropertiesSet();  
  8.         //获取客户端配置的远程调用接口   
  9.         if (getServiceInterface() == null) {  
  10.             throw new IllegalArgumentException("Property ‘serviceInterface‘ is required");  
  11.         }  
  12.         //创建远程调用代理对象并为代理对象设置拦截器。注意第二个参数this,因为   
  13.         //RmiProxyFactoryBean继承RmiClientInterceptor,因此其也是拦截器   
  14.         this.serviceProxy = new ProxyFactory(getServiceInterface(), this).getProxy(getBeanClassLoader());  
  15.     }  
  16.     //Spring IoC容器获取被管理对象的接口方法,获取远程调用代理   
  17.     public Object getObject() {  
  18.         return this.serviceProxy;  
  19.     }  
  20.     public Class<?> getObjectType() {  
  21.         return getServiceInterface();  
  22.     }  
  23.     public boolean isSingleton() {  
  24.         return true;  
  25.     }  
  26. }  

通过对上面RmiProxyFactoryBean源码分析中,我们看到在创建远程调用代理对象的时候需要设置拦截器,因为我们继续分析远程调用客户端拦截器RmiClientInterceptor

4.RmiClientInterceptor封装RMI客户端:

RmiClientInterceptor对客户端的远程调用进行拦截,具体的生成远程调用代理对象、查找远程调用stub、以及通过RMI stub向服务端发起远程调用请求的具体实现都由RMI客户端拦截器实现,其源码如下:

[java] view plaincopyprint?
  1. public class RmiClientInterceptor extends RemoteInvocationBasedAccessor  
  2.         implements MethodInterceptor {  
  3.     //在Spring启动时查找远程调用stub   
  4.     private boolean lookupStubOnStartup = true;  
  5.     //对查找到或使用过的远程调用stub进行缓存   
  6.     private boolean cacheStub = true;  
  7.     //当连接失败是是否刷新远程调用stub   
  8.     private boolean refreshStubOnConnectFailure = false;  
  9.     //RMI客户端socket工厂   
  10.     private RMIClientSocketFactory registryClientSocketFactory;  
  11.     //缓存的远程调用stub   
  12.     private Remote cachedStub;  
  13.     //创建远程调用stub监控器   
  14.     private final Object stubMonitor = new Object();  
  15. //设置是否启动时查找RMI stub   
  16.     public void setLookupStubOnStartup(boolean lookupStubOnStartup) {  
  17.         this.lookupStubOnStartup = lookupStubOnStartup;  
  18.     }  
  19.     //设置是否缓存以查找的RMI stub   
  20.     public void setCacheStub(boolean cacheStub) {  
  21.         this.cacheStub = cacheStub;  
  22.     }  
  23.     //设置当连接失败时,是否刷新RMI stub   
  24.     public void setRefreshStubOnConnectFailure(boolean refreshStubOnConnectFailure) {  
  25.         this.refreshStubOnConnectFailure = refreshStubOnConnectFailure;  
  26.     }     
  27.     //设置客户端socket工厂   
  28.     public void setRegistryClientSocketFactory(RMIClientSocketFactory registryClientSocketFactory) {  
  29.         this.registryClientSocketFactory = registryClientSocketFactory;  
  30.     }  
  31. //Spring IoC容器回调方法,由子类RmiProxyFactoryBean回调方法调用   
  32.     public void afterPropertiesSet() {  
  33.         //调用父类RemoteInvocationBasedAccessor的回调方法   
  34.         super.afterPropertiesSet();  
  35.         prepare();  
  36.     }  
  37.     //初始化RMI客户端   
  38.     public void prepare() throws RemoteLookupFailureException {  
  39.         //如果设置了启动时查找RMI stub   
  40.         if (this.lookupStubOnStartup) {  
  41.             //查找RMI stub   
  42.             Remote remoteObj = lookupStub();  
  43.             if (logger.isDebugEnabled()) {  
  44.                 //如果查找到的RMI stub是RmiInvocationHandler类型   
  45.                 if (remoteObj instanceof RmiInvocationHandler) {  
  46.                     logger.debug("RMI stub [" + getServiceUrl() + "] is an RMI invoker");  
  47.                 }  
  48.                 //如果获取到客户端配置的serviceInterface不为null   
  49.                 else if (getServiceInterface() != null) {  
  50.                     //判断客户端配置的serviceInterface是否是RMI stub实例   
  51.                     boolean isImpl = getServiceInterface().isInstance(remoteObj);  
  52.                     logger.debug("Using service interface [" + getServiceInterface().getName() +  
  53.                         "] for RMI stub [" + getServiceUrl() + "] - " +  
  54.                         (!isImpl ? "not " : "") + "directly implemented");  
  55.                 }  
  56.             }  
  57.             //如果设置了缓存RMI stub,将缓存的stub设置为查找到的RMI stub   
  58.             if (this.cacheStub) {  
  59.                 this.cachedStub = remoteObj;  
  60.             }  
  61.         }  
  62.     }  
  63.     //查找RMI stub   
  64.     protected Remote lookupStub() throws RemoteLookupFailureException {  
  65.         try {  
  66.             Remote stub = null;  
  67.             //如果设置了客户端socket工厂   
  68.             if (this.registryClientSocketFactory != null) {  
  69.                 //获取并解析客户端配置的serviceUrl   
  70.                 URL url = new URL(null, getServiceUrl(), new DummyURLStreamHandler());  
  71.                 //获取客户端配置的serviceUrl协议   
  72.                 String protocol = url.getProtocol();  
  73.                 //如果客户端配置的serviceUrl中协议不为null且不是rmi   
  74.                 if (protocol != null && !"rmi".equals(protocol)) {  
  75.                     throw new MalformedURLException("Invalid URL scheme ‘" + protocol + "‘");  
  76.                 }  
  77.                 //获取客户端配置的serviceUrl中的主机地址   
  78.                 String host = url.getHost();  
  79.                 //获取客户端配置的serviceUrl中的端口   
  80.                 int port = url.getPort();  
  81.                 //获取客户端配置的serviceUrl中请求路径   
  82.                 String name = url.getPath();  
  83.                 //如果请求路径不为null,且请求路径以”/”开头,则去掉”/”   
  84.                 if (name != null && name.startsWith("/")) {  
  85.                     name = name.substring(1);  
  86.                 }  
  87.                 //根据客户端配置的serviceUrl信息和客户端socket工厂创建远程对   
  88. //象引用   
  89.                 Registry registry = LocateRegistry.getRegistry(host, port, this.registryClientSocketFactory);  
  90.                 //通过远程对象引用查找指定RMI请求的RMI stub   
  91.                 stub = registry.lookup(name);  
  92.             }  
  93.             //如果客户端配置的serviceUrl中协议为null或者是rmi   
  94.             else {  
  95.                 //直接通过RMI标准API查找客户端配置的serviceUrl的RMI stub   
  96.                 stub = Naming.lookup(getServiceUrl());  
  97.             }  
  98.             if (logger.isDebugEnabled()) {  
  99.                 logger.debug("Located RMI stub with URL [" + getServiceUrl() + "]");  
  100.             }  
  101.             return stub;  
  102.         }  
  103.         //对查找RMI stub过程中异常处理   
  104.         catch (MalformedURLException ex) {  
  105.             throw new RemoteLookupFailureException("Service URL [" + getServiceUrl() + "] is invalid", ex);  
  106.         }  
  107.         catch (NotBoundException ex) {  
  108.             throw new RemoteLookupFailureException(  
  109.                     "Could not find RMI service [" + getServiceUrl() + "] in RMI registry", ex);  
  110.         }  
  111.         catch (RemoteException ex) {  
  112.             throw new RemoteLookupFailureException("Lookup of RMI stub failed", ex);  
  113.         }  
  114.     }  
  115.     //获取RMI stub   
  116.     protected Remote getStub() throws RemoteLookupFailureException {  
  117.         //如果没有配置缓存RMI stub,或者设置了启动时查找RMI stub或当连接失败时   
  118.         //不刷新RMI stub   
  119.         if (!this.cacheStub || (this.lookupStubOnStartup && !this.refreshStubOnConnectFailure)) {  
  120.             //如果缓存的RMI stub不为null,则直接返回,否则,查找RMI stub   
  121.             return (this.cachedStub != null ? this.cachedStub : lookupStub());  
  122.         }  
  123.         //如果设置了缓存RMI stub,且设置了启动时查找RMI stub或者当连接失败时刷新   
  124.         //RMI stub   
  125.         else {  
  126.             //线程同步   
  127.             synchronized (this.stubMonitor) {  
  128.                 //如果缓存的RMI stub为null   
  129.                 if (this.cachedStub == null) {  
  130.                     //则将查找的RMI stub缓存   
  131.                     this.cachedStub = lookupStub();  
  132.                 }  
  133.                 //返回缓存的RMI stub   
  134.                 return this.cachedStub;  
  135.             }  
  136.         }  
  137.     }  
  138.     //拦截器对客户端远程调用方法的拦截入口   
  139.     public Object invoke(MethodInvocation invocation) throws Throwable {  
  140.         //获取RMI stub   
  141.         Remote stub = getStub();  
  142.         try {  
  143.             //拦截客户端远程调用方法   
  144.             return doInvoke(invocation, stub);  
  145.         }  
  146.         catch (RemoteConnectFailureException ex) {  
  147.             return handleRemoteConnectFailure(invocation, ex);  
  148.         }  
  149.         catch (RemoteException ex) {  
  150.             if (isConnectFailure(ex)) {  
  151.                 return handleRemoteConnectFailure(invocation, ex);  
  152.             }  
  153.             else {  
  154.                 throw ex;  
  155.             }  
  156.         }  
  157.     }  
  158.     //判断是否连接失败   
  159.     protected boolean isConnectFailure(RemoteException ex) {  
  160.         return RmiClientInterceptorUtils.isConnectFailure(ex);  
  161.     }  
  162.     //处理远程连接失败   
  163.     private Object handleRemoteConnectFailure(MethodInvocation invocation, Exception ex) throws Throwable {  
  164.         //如果设置了当连接失败时,刷新RMI stub   
  165.         if (this.refreshStubOnConnectFailure) {  
  166.             String msg = "Could not connect to RMI service [" + getServiceUrl() + "] - retrying";  
  167.             if (logger.isDebugEnabled()) {  
  168.                 logger.warn(msg, ex);  
  169.             }  
  170.             else if (logger.isWarnEnabled()) {  
  171.                 logger.warn(msg);  
  172.             }  
  173.             //刷新查找远程调用stub   
  174.             return refreshAndRetry(invocation);  
  175.         }  
  176.         else {  
  177.             throw ex;  
  178.         }  
  179.     }  
  180.     //刷新RMI stub   
  181.     protected Object refreshAndRetry(MethodInvocation invocation) throws Throwable {  
  182.         Remote freshStub = null;  
  183.         //线程同步   
  184.         synchronized (this.stubMonitor) {  
  185.             this.cachedStub = null;  
  186.             //查找RMI stub   
  187.             freshStub = lookupStub();  
  188.             //如果设置了缓存RMI stub   
  189.             if (this.cacheStub) {  
  190.                 //将刷新查找的RMI stub缓存   
  191.                 this.cachedStub = freshStub;  
  192.             }  
  193.         }  
  194.         return doInvoke(invocation, freshStub);  
  195.     }  
  196.     //具体RMI调用的地方   
  197.     protected Object doInvoke(MethodInvocation invocation, Remote stub) throws Throwable {  
  198.         //如果RMI stub是RmiInvocationHandler类型   
  199.         if (stub instanceof RmiInvocationHandler) {  
  200.             //调用RmiInvocationHandler的RMI   
  201.             try {  
  202.                 return doInvoke(invocation, (RmiInvocationHandler) stub);  
  203.             }  
  204.             catch (RemoteException ex) {  
  205.                 throw RmiClientInterceptorUtils.convertRmiAccessException(  
  206.                     invocation.getMethod(), ex, isConnectFailure(ex), getServiceUrl());  
  207.             }  
  208.             catch (InvocationTargetException ex) {  
  209.                 Throwable exToThrow = ex.getTargetException();  
  210.                 RemoteInvocationUtils.fillInClientStackTraceIfPossible(exToThrow);  
  211.                 throw exToThrow;  
  212.             }  
  213.             catch (Throwable ex) {  
  214.                 throw new RemoteInvocationFailureException("Invocation of method [" + invocation.getMethod() +  
  215.                         "] failed in RMI service [" + getServiceUrl() + "]", ex);  
  216.             }  
  217.         }  
  218.         //如果RMI stub不是RmiInvocationHandler类型   
  219.         else {  
  220.             //使用传统的RMI调用方式   
  221.             try {  
  222.                 return RmiClientInterceptorUtils.invokeRemoteMethod(invocation, stub);  
  223.             }  
  224.             catch (InvocationTargetException ex) {  
  225.                 Throwable targetEx = ex.getTargetException();  
  226.                 if (targetEx instanceof RemoteException) {  
  227.                     RemoteException rex = (RemoteException) targetEx;  
  228.                     throw RmiClientInterceptorUtils.convertRmiAccessException(  
  229.                             invocation.getMethod(), rex, isConnectFailure(rex), getServiceUrl());  
  230.                 }  
  231.                 else {  
  232.                     throw targetEx;  
  233.                 }  
  234.             }  
  235.         }  
  236.     }  
  237.     //调用RmiInvocationHandler的RMI   
  238.     protected Object doInvoke(MethodInvocation methodInvocation, RmiInvocationHandler invocationHandler)  
  239.         throws RemoteException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {  
  240.         //如果客户端远程调用请求是toString()方法   
  241.         if (AopUtils.isToStringMethod(methodInvocation.getMethod())) {  
  242.             return "RMI invoker proxy for service URL [" + getServiceUrl() + "]";  
  243.         }  
  244.         //使用RmiInvocationHandler处理RMI调用   
  245.         return invocationHandler.invoke(createRemoteInvocation(methodInvocation));  
  246.     }  
  247. }  

通过上面对RmiClientInterceptor源码分析,我们看到SpringRMI远程调用使用以下两种方式:

(1).RMI调用器方式:

这种方式和Spring HTTP调用器非常类似,即使用RemoteInvocation来封装调用目标对象、目标方法、参数类型等信息,RMI服务器端接收到RMI请求之后直接调用目标对象的匹配方法。

(2).传统RMI调用方式:

使用JDK的反射机制,直接调用远程调用stub的方法。

5.RMI的服务端配置:

Spring RMI服务端需要进行类似如下的配置:

[xhtml] view plaincopyprint?
  1. <bean id=”rmiService” class=”org.springframework.remoting.rmi.RmiServiceExporter”>  
  2. <property name=”service”>  
  3. <ref bean=”RMI服务端对象”/>  
  4. </property>  
  5. <property name=”serviceInterface”>  
  6. <value>RMI服务接口</value>  
  7. </property>  
  8. <property name=”serviceName”>  
  9. <value>RMI服务导出名称</value>  
  10. </property>  
  11. <property name=”registerPort”>  
  12. <value>1099</value>  
  13. </property>  
  14. </bean>  

RMI中,基于TCP/IP协议,而不是HTTP协议来实现底层网络通信,由于RMI的网络通信已由Java RMI实现,所以这里不再使用Spring MVC的DispatcherServlet来转发客户端配置的远程调用请求URL,只需要指定RMI的TCP/.IP监听端口和服务导出的名称即可。

6.RmiServiceExporter导出RMI远程调用对象:

RmiServiceExporter主要功能是将服务端远程对象提供的服务导出供客户端请求调用,同时将导出的远程对象和注册器绑定起来供客户端查询,其主要源码如下:

[java] view plaincopyprint?
  1. public class RmiServiceExporter extends RmiBasedExporter implements InitializingBean, DisposableBean {  
  2.     //导出的RMI服务名称   
  3.     private String serviceName;  
  4.     //RMI服务端口   
  5.     private int servicePort = 0;    
  6.     //RMI客户端socket工厂   
  7.     private RMIClientSocketFactory clientSocketFactory;  
  8.     //RMI服务端socket工厂   
  9.     private RMIServerSocketFactory serverSocketFactory;  
  10.     //注册器   
  11.     private Registry registry;  
  12.     //注册主机   
  13.     private String registryHost;  
  14.     //注册端口   
  15.     private int registryPort = Registry.REGISTRY_PORT;  
  16.     //客户端注册socket工厂   
  17.     private RMIClientSocketFactory registryClientSocketFactory;  
  18.     //服务端注册socket工厂   
  19.     private RMIServerSocketFactory registryServerSocketFactory;  
  20.     //总是创建时注册   
  21.     private boolean alwaysCreateRegistry = false;  
  22.     //替换已有的绑定   
  23.     private boolean replaceExistingBinding = true;  
  24.     //导出的远程对象   
  25.     private Remote exportedObject;  
  26.     //创建注册   
  27.     private boolean createdRegistry = false;  
  28.     //注入服务端配置的RMI导出服务名称,格式为:“rmi://host:post/NAME”   
  29.     public void setServiceName(String serviceName) {  
  30.         this.serviceName = serviceName;  
  31.     }  
  32.     //设置服务端口   
  33.     public void setServicePort(int servicePort) {  
  34.         this.servicePort = servicePort;  
  35.     }  
  36.     //设置RMI客户端socket工厂   
  37.     public void setClientSocketFactory(RMIClientSocketFactory clientSocketFactory) {  
  38.         this.clientSocketFactory = clientSocketFactory;  
  39.     }  
  40.     //设置RMI服务端socket工厂   
  41.     public void setServerSocketFactory(RMIServerSocketFactory serverSocketFactory) {  
  42.         this.serverSocketFactory = serverSocketFactory;  
  43.     }  
  44.     //设置RMI注册器   
  45.     public void setRegistry(Registry registry) {  
  46.         this.registry = registry;  
  47.     }  
  48.     //设置RMI注册主机   
  49.     public void setRegistryHost(String registryHost) {  
  50.         this.registryHost = registryHost;  
  51.     }  
  52.     //设置RMI注册端口   
  53.     public void setRegistryPort(int registryPort) {  
  54.         this.registryPort = registryPort;  
  55.     }  
  56.     //设置用于注册的RMI客户端socket工厂   
  57.     public void setRegistryClientSocketFactory(RMIClientSocketFactory registryClientSocketFactory) {  
  58.         this.registryClientSocketFactory = registryClientSocketFactory;  
  59.     }  
  60. //设置用于注册的RMI服务端socket工厂   
  61.     public void setRegistryServerSocketFactory(RMIServerSocketFactory registryServerSocketFactory) {  
  62.         this.registryServerSocketFactory = registryServerSocketFactory;  
  63.     }  
  64.     //设置是否总是创建注册,而不是试图查找指定端口上已有的注册   
  65.     public void setAlwaysCreateRegistry(boolean alwaysCreateRegistry) {  
  66.         this.alwaysCreateRegistry = alwaysCreateRegistry;  
  67.     }  
  68.     //设置是否提供已绑定的RMI注册   
  69.     public void setReplaceExistingBinding(boolean replaceExistingBinding) {  
  70.         this.replaceExistingBinding = replaceExistingBinding;  
  71.     }  
  72.     //IoC容器依赖注入完成之后的回调方法   
  73.     public void afterPropertiesSet() throws RemoteException {  
  74.         prepare();  
  75.     }  
  76.     //初始化RMI服务导出器   
  77.     public void prepare() throws RemoteException {  
  78.         //调用其父类RmiBasedExporter的方法,检查服务引用是否被设置   
  79.         checkService();  
  80.         //如果服务导出名称为null   
  81.         if (this.serviceName == null) {  
  82.             throw new IllegalArgumentException("Property ‘serviceName‘ is required");  
  83.         }  
  84.         //检查socket工厂   
  85.         if (this.clientSocketFactory instanceof RMIServerSocketFactory) {  
  86.             this.serverSocketFactory = (RMIServerSocketFactory) this.clientSocketFactory;  
  87.         }  
  88.         if ((this.clientSocketFactory != null && this.serverSocketFactory == null) ||  
  89.                 (this.clientSocketFactory == null && this.serverSocketFactory != null)) {  
  90.             throw new IllegalArgumentException(  
  91.                     "Both RMIClientSocketFactory and RMIServerSocketFactory or none required");  
  92.         }  
  93.         //检查RMI注册的socket工厂   
  94.         if (this.registryClientSocketFactory instanceof RMIServerSocketFactory) {  
  95.             this.registryServerSocketFactory = (RMIServerSocketFactory) this.registryClientSocketFactory;  
  96.         }  
  97.         if (this.registryClientSocketFactory == null && this.registryServerSocketFactory != null) {  
  98.             throw new IllegalArgumentException(  
  99.                     "RMIServerSocketFactory without RMIClientSocketFactory for registry not supported");  
  100.         }  
  101.         this.createdRegistry = false;  
  102.         //获取RMI注册器   
  103.         if (this.registry == null) {  
  104.             this.registry = getRegistry(this.registryHost, this.registryPort,  
  105.                 this.registryClientSocketFactory, this.registryServerSocketFactory);  
  106.             this.createdRegistry = true;  
  107.         }  
  108.         //获取要被导出的服务端远程对象   
  109.         this.exportedObject = getObjectToExport();  
  110.         if (logger.isInfoEnabled()) {  
  111.             logger.info("Binding service ‘" + this.serviceName + "‘ to RMI registry: " + this.registry);  
  112.         }  
  113.         //导出远程服务对象   
  114.         if (this.clientSocketFactory != null) {  
  115.             UnicastRemoteObject.exportObject(  
  116.                     this.exportedObject, this.servicePort, this.clientSocketFactory, this.serverSocketFactory);  
  117.         }  
  118.         else {  
  119.             UnicastRemoteObject.exportObject(this.exportedObject, this.servicePort);  
  120.         }  
  121.         //将RMI对象绑定到注册器   
  122.         try {  
  123.             if (this.replaceExistingBinding) {  
  124.                 this.registry.rebind(this.serviceName, this.exportedObject);  
  125.             }  
  126.             else {  
  127.                 this.registry.bind(this.serviceName, this.exportedObject);  
  128.             }  
  129.         }  
  130.         //异常处理   
  131.         catch (AlreadyBoundException ex) {  
  132.             unexportObjectSilently();  
  133.             throw new IllegalStateException(  
  134.                     "Already an RMI object bound for name ‘"  + this.serviceName + "‘: " + ex.toString());  
  135.         }  
  136.         catch (RemoteException ex) {  
  137.             unexportObjectSilently();  
  138.             throw ex;  
  139.         }  
  140.     }  
  141.     ……  
  142. }   

7.RemoteInvocationBasedExporter处理RMI远程调用请求:

RmiServiceExporter的父类RmiBasedExporter的父类RemoteInvocationBasedExporter负责对RMI远程调用请求进行处理,并将处理的结果封装返回,其源码如下:

[java] view plaincopyprint?
  1. public abstract class RemoteInvocationBasedExporter extends RemoteExporter {  
  2. //RMI远程调用处理器,RMI远程调用请求是由DefaultRemoteInvocationExecutor处理   
  3.     private RemoteInvocationExecutor remoteInvocationExecutor = new DefaultRemoteInvocationExecutor();  
  4. //设置RMI远程调用处理器   
  5.     public void setRemoteInvocationExecutor(RemoteInvocationExecutor remoteInvocationExecutor) {  
  6.         this.remoteInvocationExecutor = remoteInvocationExecutor;  
  7.     }  
  8.     //获取RMI远程调用处理器   
  9.     public RemoteInvocationExecutor getRemoteInvocationExecutor() {  
  10.         return this.remoteInvocationExecutor;  
  11.     }  
  12. //对RMI远程调用请求进行处理的地方   
  13.     protected Object invoke(RemoteInvocation invocation, Object targetObject)  
  14.             throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {  
  15.         if (logger.isTraceEnabled()) {  
  16.             logger.trace("Executing " + invocation);  
  17.         }  
  18.         try {  
  19.             //调用DefaultRemoteInvocationExecutor对RMI远程调用请求进行处理   
  20.             return getRemoteInvocationExecutor().invoke(invocation, targetObject);  
  21.         }  
  22.         catch (NoSuchMethodException ex) {  
  23.             if (logger.isDebugEnabled()) {  
  24.                 logger.warn("Could not find target method for " + invocation, ex);  
  25.             }  
  26.             throw ex;  
  27.         }  
  28.         catch (IllegalAccessException ex) {  
  29.             if (logger.isDebugEnabled()) {  
  30.                 logger.warn("Could not access target method for " + invocation, ex);  
  31.             }  
  32.             throw ex;  
  33.         }  
  34.         catch (InvocationTargetException ex) {  
  35.             if (logger.isDebugEnabled()) {  
  36.                 logger.debug("Target method failed for " + invocation, ex.getTargetException());  
  37.             }  
  38.             throw ex;  
  39.         }  
  40.     }  
  41.     //获取RMI远程调用请求的处理结果   
  42.     protected RemoteInvocationResult invokeAndCreateResult(RemoteInvocation invocation, Object targetObject) {  
  43.         try {  
  44.             Object value = invoke(invocation, targetObject);  
  45.             return new RemoteInvocationResult(value);  
  46.         }  
  47.         catch (Throwable ex) {  
  48.             return new RemoteInvocationResult(ex);  
  49.         }  
  50.     }  
  51. }  

RMI远程调用请求最终由DefaultRemoteInvocationExecutor处理。

8.DefaultRemoteInvocationExecutor处理RMI远程调用请求:

DefaultRemoteInvocationExecutor用于处理RMI远程调用请求,并返回处理后的结果,其源码如下:

[java] view plaincopyprint?
  1. public class DefaultRemoteInvocationExecutor implements RemoteInvocationExecutor {  
  2.     //处理RMI远程调用请求   
  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处理RMI远程调用请求   
  8.         return invocation.invoke(targetObject);  
  9.     }  
  10. }  

9.RemoteInvocation处理RMI远程调用请求:

RemoteInvocationinvoke方法处理RMI远程调用请求,并返回远程调用处理后的结果,其源码如下:

[java] view plaincopyprint?
  1. public Object invoke(Object targetObject)  
  2.             throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {  
  3.         //使用JDK反射机制获取远程调用服务端目标对象的方法   
  4.         Method method = targetObject.getClass().getMethod(this.methodName, this.parameterTypes);  
  5.         //使用JDK反射机制调用目标对象的方法   
  6.         return method.invoke(targetObject, this.arguments);  
  7.     }  

Spring框架学习【Spring RMI实现远程调用】

上一篇:远程无法连接或使用IP无法连接,提示连接拒绝


下一篇:Linux开发环境必备十大开发工具