spring5.1.x源码解析之十(spring-rmi)

RMI demo

package org.example.rmi.test;

import java.rmi.*;

public interface MyRemote extends Remote {
	public String sayHello() throws RemoteException;
}

package org.example.rmi.test;

import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.server.UnicastRemoteObject;


/**
 * 1:制作远程接口 定义接口继承remote, 声明所有方法抛出RemoteException 变量以及返回值属于原语类型或可序列化 
 * 2:制作远程实现实现接口,成为远程服务对象简单继承UnicastRemoteObject
 * 				UnicastRemoteObject构造器会抛出异常,所以实现类提供构造抛出异常
 * 				实例化后,注册Naming.rebind,RMI注册的是stub(需要提前启动RMI Registry) 
 * 3:产生stub和skeleton:rmic MyRemoteImpl 
 * 4:执行:rmiregistry 
 * 5:启动服务:java MyRemoteImpl
 * 6:客户根据stub对象调用代理方法,需要stub类,之前利用rmic产生的 
 * 		MyRemote service = (MyRemote)Naming.lookup("rmi://127.0.0.1/RemoteHello"); 
 * 工作方式 从RMIregistry中找Naming.lookup("rmi://127.0.0.1/RemoteHello"); 返回stub对象调用stub方法,获取结果
 * 
 * 扩展获取stub方法:动态类下载,本地下不到从url下
 */
public class MyRemoteImpl extends UnicastRemoteObject implements MyRemote {

	private static final long serialVersionUID = 1L;

	protected MyRemoteImpl() throws RemoteException {
	}

	// 不需要声明异常
	public String sayHello() throws RemoteException {
		return "hello";
	}

	public static void main(String[] args) {
		try {
			MyRemote service = new MyRemoteImpl();
			
			//一定要注册表创建端口
			LocateRegistry.createRegistry(6600);
			// 服务名,注册实例
			//Naming.rebind("rmi://192.168.30.1:6600/MyRemote", service);
			Naming.rebind("rmi://192.168.2.106:6600/MyRemote", service);
			/*
				Context namingContext = new InitialContext();
				namingContext.rebind("//127.0.0.1:6600/MyRemote",
						service);*/
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

package org.example.rmi.test;

import java.rmi.Naming;

public class MyRemoteClient {
	public static void main(String[] args) {
		new MyRemoteClient().go();
	}

	private void go() {
		try {
			MyRemote service = (MyRemote) Naming
					.lookup("rmi://127.0.0.1:6600/MyRemote");
			String s = service.sayHello();
			System.out.println(s);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

spring整合RMI

service端

package org.example.rmi.spring;

import org.example.rmi.test.MyRemote;

import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.server.UnicastRemoteObject;

public class MyRemoteServiceImpl implements MyRemoteService {


    @Override
    public String sayHello() {
        return "hello";
    }
}

package org.example.rmi.spring;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface MyRemoteService {
    public String sayHello();
}

package org.example.rmi.spring;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Hello world!
 */
public class ServiceApp {
    public static void main(String[] args) {
        ApplicationContext bf2 = new ClassPathXmlApplicationContext("rmi/rmi-service.xml");
    }
}

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context.xsd">

    <bean id="myRemoteService" class="org.example.rmi.spring.MyRemoteServiceImpl"/>
    <bean name="rmiServiceExporter"  class="org.springframework.remoting.rmi.RmiServiceExporter">
        <!--服务类-->
        <property name="service" ref="myRemoteService"></property>
        <!--服务接口-->
        <property name="serviceInterface" value="org.example.rmi.spring.MyRemoteService"></property>
        <!--服务名-->
        <property name="serviceName" value="hello"></property>
        <!--暴露端口-->
        <property name="registryPort" value="6600"></property>

    </bean>
</beans>

client端

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context.xsd">

    <bean name="client" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
        <property name="serviceUrl"  value="rmi://127.0.0.1:6600/hello"></property>
        <property name="serviceInterface" value="org.example.rmi.spring.MyRemoteService"></property>
    </bean>
</beans>
package org.example.rmi.spring;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Hello world!
 */
public class ClientApp {
    public static void main(String[] args) {
        ApplicationContext bf2 = new ClassPathXmlApplicationContext("rmi/rmi-client.xml");
        MyRemoteService bean = bf2.getBean("client", MyRemoteService.class);
        System.out.println(bean.sayHello());
    }
}

服务端解析

查看RmiServiceExporter接口继承层次
可以看到分别继承了
InitializingBean:初始化时调用
DisposableBean:销毁时调用
BeanClassLoaderAware:注入类加载器
在这里插入图片描述

绑定,注册

查看初始化调用方法

	@Override
	public void afterPropertiesSet() throws RemoteException {
		prepare();
	}
/*
	验证
	处理用户自定义4个属性
	确定使用的RMI-registry
	初始化以及缓存导出的对象
	导出RMI对象
	绑定服务名到RMI object
	 */
	public void prepare() throws RemoteException {
		//验证service
		checkService();

		if (this.serviceName == null) {
			throw new IllegalArgumentException("Property 'serviceName' is required");
		}

		// Check socket factories for exported object.
		//导出远程对象
			//如果clientSocketFactory实现了RMIServerSocketFactory
			// 则覆盖serverSocketFactory采用clientSocketFactory代替
		if (this.clientSocketFactory instanceof RMIServerSocketFactory) {
			this.serverSocketFactory = (RMIServerSocketFactory) this.clientSocketFactory;
		}
		//clientSocketFactory和serverSocketFactory全部出现或者全部都不出现
		if ((this.clientSocketFactory != null && this.serverSocketFactory == null) ||
				(this.clientSocketFactory == null && this.serverSocketFactory != null)) {
			throw new IllegalArgumentException(
					"Both RMIClientSocketFactory and RMIServerSocketFactory or none required");
		}

		// Check socket factories for RMI registry.
		//用于主机与RMI服务器之间连接
			//如果registryClientSocketFactory实现了RMIServerSocketFactory
			//则覆盖registryServerSocketFactory采用registryClientSocketFactory代替
		if (this.registryClientSocketFactory instanceof RMIServerSocketFactory) {
			this.registryServerSocketFactory = (RMIServerSocketFactory) this.registryClientSocketFactory;
		}
		//registryServerSocketFactory不为空,registryClientSocketFactory为空则异常
		if (this.registryClientSocketFactory == null && this.registryServerSocketFactory != null) {
			throw new IllegalArgumentException(
					"RMIServerSocketFactory without RMIClientSocketFactory for registry not supported");
		}

		this.createdRegistry = false;

		// Determine RMI registry to use.
		//确定使用的RMI-registry
		if (this.registry == null) {
			this.registry = getRegistry(this.registryHost, this.registryPort,
				this.registryClientSocketFactory, this.registryServerSocketFactory);
			this.createdRegistry = true;
		}

		// Initialize and cache exported object.
		//初始化以及缓存导出的对象,外界调用会被此对象接收
		this.exportedObject = getObjectToExport();

		if (logger.isDebugEnabled()) {
			logger.debug("Binding service '" + this.serviceName + "' to RMI registry: " + this.registry);
		}

		// Export RMI object.
		if (this.clientSocketFactory != null) {
			/*
			clientSocketFactory:进行远程对象调用的客户端socket工厂
			serverSocketFactory:接收远程对象调用的服务端socket工厂
			 */
			UnicastRemoteObject.exportObject(
					this.exportedObject, this.servicePort, this.clientSocketFactory, this.serverSocketFactory);
		}
		else {
			//导出RMI对象,以便能接受特定端口调用
			UnicastRemoteObject.exportObject(this.exportedObject, this.servicePort);
		}

		// Bind RMI object to registry.
		try {
			if (this.replaceExistingBinding) {
				this.registry.rebind(this.serviceName, this.exportedObject);
			}
			else {
				//绑定服务名到 RMI object
				this.registry.bind(this.serviceName, this.exportedObject);
			}
		}
		catch (AlreadyBoundException ex) {
			// Already an RMI object bound for the specified service name...
			unexportObjectSilently();
			throw new IllegalStateException(
					"Already an RMI object bound for name '"  + this.serviceName + "': " + ex.toString());
		}
		catch (RemoteException ex) {
			// Registry binding failed: let's unexport the RMI object as well.
			unexportObjectSilently();
			throw ex;
		}
	}
protected Registry getRegistry(String registryHost, int registryPort,
			@Nullable RMIClientSocketFactory clientSocketFactory, @Nullable RMIServerSocketFactory serverSocketFactory)
			throws RemoteException {

		if (registryHost != null) {
			// Host explicitly specified: only lookup possible.
			if (logger.isDebugEnabled()) {
				logger.debug("Looking for RMI registry at port '" + registryPort + "' of host [" + registryHost + "]");
			}
			//如果registryHost不为空,则尝试获取对应主机的Registry
			Registry reg = LocateRegistry.getRegistry(registryHost, registryPort, clientSocketFactory);
			testRegistry(reg);
			return reg;
		}

		else {
			//获取本机Registry
			return getRegistry(registryPort, clientSocketFactory, serverSocketFactory);
		}
	}
/*
	新建
	复用
	根据端口直接创建
	 */
	protected Registry getRegistry(int registryPort,
			@Nullable RMIClientSocketFactory clientSocketFactory, @Nullable RMIServerSocketFactory serverSocketFactory)
			throws RemoteException {

		if (clientSocketFactory != null) {
			if (this.alwaysCreateRegistry) {
				logger.debug("Creating new RMI registry");
				//使用clientSocketFactory新建
				return LocateRegistry.createRegistry(registryPort, clientSocketFactory, serverSocketFactory);
			}
			if (logger.isDebugEnabled()) {
				logger.debug("Looking for RMI registry at port '" + registryPort + "', using custom socket factory");
			}
			synchronized (LocateRegistry.class) {
				try {
					// Retrieve existing registry.
					//复用
					Registry reg = LocateRegistry.getRegistry(null, registryPort, clientSocketFactory);
					//测试是否可用,不可用直接异常
					testRegistry(reg);
					return reg;
				}
				catch (RemoteException ex) {
					logger.trace("RMI registry access threw exception", ex);
					logger.debug("Could not detect RMI registry - creating new one");
					// Assume no registry found -> create new one.
					//根据端口创建
					return LocateRegistry.createRegistry(registryPort, clientSocketFactory, serverSocketFactory);
				}
			}
		}

		else {
			//直接根据端口调用
			return getRegistry(registryPort);
		}
	}

/*
	采用自定义实现Remote类调用
	采用spring封装RmiInvocationWrapper然后经过代理对象调用
	 */
	protected Remote getObjectToExport() {
		// determine remote object
		//如果配置的service属性继承了Remote接口且没配置serviceInterface属性
		if (getService() instanceof Remote &&
				(getServiceInterface() == null || Remote.class.isAssignableFrom(getServiceInterface()))) {
			// conventional RMI service
			//直接使用service作为处理类
			return (Remote) getService();
		}
		else {
			// RMI invoker
			if (logger.isDebugEnabled()) {
				logger.debug("RMI service [" + getService() + "] is an RMI invoker");
			}
			//对service的代理类和当前类RMIServiceExporter封装
			//当调用的时候,会执行invoke,invoke调用代理方法,代理方法调用service,之所以添加代理是为了更高的灵活性
			return new RmiInvocationWrapper(getProxyForService(), this);
		}
	}

protected Object getProxyForService() {
		//验证service
		checkService();
		//验证service接口
		checkServiceInterface();

		//使用JDK代理
		ProxyFactory proxyFactory = new ProxyFactory();
		//添加代理接口
		proxyFactory.addInterface(getServiceInterface());

		if (this.registerTraceInterceptor != null ? this.registerTraceInterceptor : this.interceptors == null) {
			//加入代理的拦截器
			proxyFactory.addAdvice(new RemoteInvocationTraceInterceptor(getExporterName()));
		}
		if (this.interceptors != null) {
			AdvisorAdapterRegistry adapterRegistry = GlobalAdvisorAdapterRegistry.getInstance();
			for (Object interceptor : this.interceptors) {
				proxyFactory.addAdvisor(adapterRegistry.wrap(interceptor));
			}
		}

		//设置代理目标类
		proxyFactory.setTarget(getService());
		proxyFactory.setOpaque(true);

		//创建代理
		return proxyFactory.getProxy(getBeanClassLoader());
	}

调用

RmiInvocationWrapper.invoke

	@Override
	@Nullable
	public Object invoke(RemoteInvocation invocation)
		throws RemoteException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {

		return this.rmiExporter.invoke(invocation, this.wrappedObject);
	}
	@Override
	protected Object invoke(RemoteInvocation invocation, Object targetObject)
			throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {

		return super.invoke(invocation, targetObject);
	}
protected Object invoke(RemoteInvocation invocation, Object targetObject)
			throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {

		if (logger.isTraceEnabled()) {
			logger.trace("Executing " + invocation);
		}
		try {
			return getRemoteInvocationExecutor().invoke(invocation, targetObject);
		}
		catch (NoSuchMethodException ex) {
			if (logger.isDebugEnabled()) {
				logger.debug("Could not find target method for " + invocation, ex);
			}
			throw ex;
		}
		catch (IllegalAccessException ex) {
			if (logger.isDebugEnabled()) {
				logger.debug("Could not access target method for " + invocation, ex);
			}
			throw ex;
		}
		catch (InvocationTargetException ex) {
			if (logger.isDebugEnabled()) {
				logger.debug("Target method failed for " + invocation, ex.getTargetException());
			}
			throw ex;
		}
	}
	@Override
	public Object invoke(RemoteInvocation invocation, Object targetObject)
			throws NoSuchMethodException, IllegalAccessException, InvocationTargetException{

		Assert.notNull(invocation, "RemoteInvocation must not be null");
		Assert.notNull(targetObject, "Target object must not be null");
		//通过反射调用
		return invocation.invoke(targetObject);
	}

	public Object invoke(Object targetObject)
			throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {

		//根据方法名获得代理中对应方法
		Method method = targetObject.getClass().getMethod(this.methodName, this.parameterTypes);
		//执行代理方法
		return method.invoke(targetObject, this.arguments);
	}

客户端解析

在这里插入图片描述

	@Override
	public void afterPropertiesSet() {
		super.afterPropertiesSet();
		Class<?> ifc = getServiceInterface();
		Assert.notNull(ifc, "Property 'serviceInterface' is required");
		//使用当前类作为代理类拦截器
		this.serviceProxy = new ProxyFactory(ifc, this).getProxy(getBeanClassLoader());
	}

	@Override
	public void afterPropertiesSet() {
		super.afterPropertiesSet();
		prepare();
	}

	public void afterPropertiesSet() {
		if (getServiceUrl() == null) {
			throw new IllegalArgumentException("Property 'serviceUrl' is required");
		}
	}
public void prepare() throws RemoteLookupFailureException {
		// Cache RMI stub on initialization?
		//如果配置了lookupStubOnStartup,会在启动时寻找stub
		if (this.lookupStubOnStartup) {
			Remote remoteObj = lookupStub();
			if (logger.isDebugEnabled()) {
				if (remoteObj instanceof RmiInvocationHandler) {
					logger.debug("RMI stub [" + getServiceUrl() + "] is an RMI invoker");
				}
				else if (getServiceInterface() != null) {
					boolean isImpl = getServiceInterface().isInstance(remoteObj);
					logger.debug("Using service interface [" + getServiceInterface().getName() +
						"] for RMI stub [" + getServiceUrl() + "] - " +
						(!isImpl ? "not " : "") + "directly implemented");
				}
			}
			if (this.cacheStub) {
				//缓存stub
				this.cachedStub = remoteObj;
			}
		}
	}
protected Remote lookupStub() throws RemoteLookupFailureException {
		try {
			Remote stub = null;
			if (this.registryClientSocketFactory != null) {
				// RMIClientSocketFactory specified for registry access.
				// Unfortunately, due to RMI API limitations, this means
				// that we need to parse the RMI URL ourselves and perform
				// straight LocateRegistry.getRegistry/Registry.lookup calls.
				URL url = new URL(null, getServiceUrl(), new DummyURLStreamHandler());
				String protocol = url.getProtocol();
				//验证传输协议
				if (protocol != null && !"rmi".equals(protocol)) {
					throw new MalformedURLException("Invalid URL scheme '" + protocol + "'");
				}
				//获取端口和主机
				String host = url.getHost();
				int port = url.getPort();
				//获取服务名
				String name = url.getPath();
				if (name != null && name.startsWith("/")) {
					name = name.substring(1);
				}
				Registry registry = LocateRegistry.getRegistry(host, port, this.registryClientSocketFactory);
				stub = registry.lookup(name);
			}
			else {
				// Can proceed with standard RMI lookup API...
				stub = Naming.lookup(getServiceUrl());
			}
			if (logger.isDebugEnabled()) {
				logger.debug("Located RMI stub with URL [" + getServiceUrl() + "]");
			}
			return stub;
		}
		catch (MalformedURLException ex) {
			throw new RemoteLookupFailureException("Service URL [" + getServiceUrl() + "] is invalid", ex);
		}
		catch (NotBoundException ex) {
			throw new RemoteLookupFailureException(
					"Could not find RMI service [" + getServiceUrl() + "] in RMI registry", ex);
		}
		catch (RemoteException ex) {
			throw new RemoteLookupFailureException("Lookup of RMI stub failed", ex);
		}
	}

执行

	public Object invoke(MethodInvocation invocation) throws Throwable {
		//获取服务器中对应注册的remote对象,序列化传输
		Remote stub = getStub();
		try {
			return doInvoke(invocation, stub);
		}
		catch (RemoteConnectFailureException ex) {
			return handleRemoteConnectFailure(invocation, ex);
		}
		catch (RemoteException ex) {
			if (isConnectFailure(ex)) {
				return handleRemoteConnectFailure(invocation, ex);
			}
			else {
				throw ex;
			}
		}
	}
	/*
	如果是RmiInvocationHandler类型,采用spring方式执行
	不是,则采用反射执行
	 */
	protected Object doInvoke(MethodInvocation invocation, Remote stub) throws Throwable {
		//如果是RmiInvocationHandler类型,则spring管理,则采用spring构建
		if (stub instanceof RmiInvocationHandler) {
			// RMI invoker
			try {
				return doInvoke(invocation, (RmiInvocationHandler) stub);
			}
			catch (RemoteException ex) {
				throw RmiClientInterceptorUtils.convertRmiAccessException(
					invocation.getMethod(), ex, isConnectFailure(ex), getServiceUrl());
			}
			catch (InvocationTargetException ex) {
				Throwable exToThrow = ex.getTargetException();
				RemoteInvocationUtils.fillInClientStackTraceIfPossible(exToThrow);
				throw exToThrow;
			}
			catch (Throwable ex) {
				throw new RemoteInvocationFailureException("Invocation of method [" + invocation.getMethod() +
						"] failed in RMI service [" + getServiceUrl() + "]", ex);
			}
		}
		else {
			// traditional RMI stub
			try {
				//如果是其他第三方的插件生成的remote,则直接反射调用
				return RmiClientInterceptorUtils.invokeRemoteMethod(invocation, stub);
			}
			catch (InvocationTargetException ex) {
				Throwable targetEx = ex.getTargetException();
				if (targetEx instanceof RemoteException) {
					RemoteException rex = (RemoteException) targetEx;
					throw RmiClientInterceptorUtils.convertRmiAccessException(
							invocation.getMethod(), rex, isConnectFailure(rex), getServiceUrl());
				}
				else {
					throw targetEx;
				}
			}
		}
	}

由于继承了FactoryBean,所以最终调用getObject获取对象

	@Override
	public Object getObject() {
		return this.serviceProxy;
	}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值