Spring系列-Spring远端调用原理分析

本文深入分析了Spring的Http调用器,包括客户端和服务端的工作原理。客户端通过HttpInvokerProxyFactoryBean创建代理,利用HttpInvokerClientInterceptor进行方法调用封装并发送HTTP请求。服务端通过HttpInvokerServiceExporter接收请求,反序列化调用信息,使用反射执行方法,并将结果序列化回传。整个过程涉及Java序列化和HTTP通信。
摘要由CSDN通过智能技术生成

背景:
在分布式计算中,经常涉及到多服务器之间不同进程的通信与计算交互,所以就需要用到远端调用。比如可以基于Http进行调用,或者WebService技术,或者RMI。通过这种技术,就可以进行服务能力的扩展,实现分布式计算。

Spring为远端调用的实现提供了许多不同的方案,比如Http调用器、第三方远端调用库Hessian/Burlap、RMI、基于Java RMI的解决方案等。这几种方案的套路其实都差不多,接下来我们就只看一下Http调用器的设计和实现原理。

Spring Http调用器
这个调用器,顾名思义,是基于HTTP协议的远程调用,分为客户端和服务端。客户端的功能是打开Http连接,将请求对象序列化,将请求发送给服务端。对于服务端来说,负责接收请求,将请求中对象反序列化,处理请求,把结果序列化之后通过http返回到客户端。接下来就看下具体的代码。

Http调用器客户端
客户端的服务配置是通过HttpInvokerProxyFactoryBean实现的,下面是HttpInvokerProxyFactoryBean的定义:

public class HttpInvokerProxyFactoryBean extends HttpInvokerClientInterceptor
		implements FactoryBean<Object> {

	private Object serviceProxy;


	@Override
	public void afterPropertiesSet() {
		super.afterPropertiesSet();
		if (getServiceInterface() == null) {
			throw new IllegalArgumentException("Property 'serviceInterface' is required");
		}
		this.serviceProxy = new ProxyFactory(getServiceInterface(), this).getProxy(getBeanClassLoader());
	}


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

	@Override
	public Class<?> getObjectType() {
		return getServiceInterface();
	}

	@Override
	public boolean isSingleton() {
		return true;
	}

}

HttpInvokerProxyFactoryBean间接实现了InitializingBean接口,重写了afterPropertiesSet方法。在afterPropertiesSet方法中,生成了一个代理对象,赋值给了serviceProxy。在new ProxyFactory的时候,构造函数第二个参数,传入了this,这个参数是接收一个Interceptor对象的,HttpInvokerProxyFactoryBean继承了HttpInvokerClientInterceptor,所以这个Interceptor对象就是HttpInvokerClientInterceptor。这个参数会作为一个Advice设置到代理对象中。
根据之前分析过的Spring AOP的实现原理,Advice会设置为代理对象的拦截器,在调用目标对象方法是,会触发代理对象中的拦截器方法,所以,我们再看下HttpInvokerClientInterceptor中的invoke代码:

@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
	if (AopUtils.isToStringMethod(methodInvocation.getMethod())) {
		return "HTTP invoker proxy for service URL [" + getServiceUrl() + "]";
	}

	// 创建RemoteInvocation对象,封装了对远端的调用信息
	RemoteInvocation invocation = createRemoteInvocation(methodInvocation);
	RemoteInvocationResult result;
	try {
		// 实际的调用入口
		result = executeRequest(invocation, methodInvocation);
	}
	catch (Throwable ex) {
		throw convertHttpInvokerAccessException(ex);
	}
	try {
		// 	返回结果
		return recreateRemoteInvocationResult(result);
	}
	catch (Throwable ex) {
		if (result.hasInvocationTargetException()) {
			throw ex;
		}
		else {
			throw new RemoteInvocationFailureException("
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值