大家好,我是小趴菜,接下来我会从0到1手写一个RPC框架,该专题包括以下专题,有兴趣的小伙伴就跟着我一起学习吧
本章源码地址:gitee.com/baojh123/se…
自定义注解 -> opt-01
服务提供者收发消息基础实现 -> opt-01
自定义网络传输协议的实现 -> opt-02
自定义编解码实现 -> opt-03
服务提供者调用真实方法实现 -> opt-04
完善服务消费者发送消息基础功能 -> opt-05
注册中心基础功能实现 -> opt-06
服务提供者整合注册中心 -> opt-07
服务消费者整合注册中心 -> opt-08
完善服务消费者接收响应结果 -> opt-09
服务消费者,服务提供者整合SpringBoot -> opt-10
动态代理屏蔽RPC服务调用底层细节 -> opt-10
SPI机制基础功能实现 -> opt-11
SPI机制扩展随机负载均衡策略 -> opt-12
SPI机制扩展轮询负载均衡策略 -> opt-13
SPI机制扩展JDK序列化 -> opt-14
SPI机制扩展JSON序列化 -> opt-15
SPI机制扩展protustuff序列化 -> opt-16
前言
在上一章中,我们已经成功的将服务提供者和服务消费者与SpringBoot成功整合了。但是在那一章中,我们已经实现了基于动态代理来屏蔽了RPC顶层服务调用的细节,这一章来说明如何去实现动态代理
实现
新建 xpc-rpc-proxy 代理模块,然后在创建二个子模块
- com.xpc.proxy.common.ObjectProxy
package com.xpc.proxy.common;
import com.xpc.proxy.common.consumer.Consumer;
import com.xpc.rpc.common.enums.RpcMsgType;
import com.xpc.rpc.protocol.ProtocolMessage;
import com.xpc.rpc.protocol.header.RpcHeader;
import com.xpc.rpc.protocol.request.RpcRequest;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class ObjectProxy implements InvocationHandler {
private Consumer consumer;
private Class clazz;
public ObjectProxy(Consumer consumer,Class clazz) {
this.consumer = consumer;
this.clazz = clazz;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//开始构造请求对象
ProtocolMessage rpcRequestProtocolMessage = new ProtocolMessage();
RpcRequest rpcRequest = new RpcRequest();
RpcHeader rpcHeader = new RpcHeader();
rpcHeader.setMsgType(RpcMsgType.REQUEST.getType());
rpcHeader.setRequestId(1L);
rpcRequestProtocolMessage.setRpcHeader(rpcHeader);
rpcRequest.setClassName(clazz.getName());
rpcRequest.setMethodName(method.getName());
rpcRequest.setParameterTypes(method.getParameterTypes());
rpcRequest.setParameters(args);
rpcRequestProtocolMessage.setT(rpcRequest);
//发送请求
return consumer.sendRequest(rpcRequestProtocolMessage);
}
}
- Consumer:客户端发送请求的接口,RpcConsumer是它的具体实现
- Class:代理接口的class,我们是给接口直接进行代理,所以这个Class也就是这个被代理的
接口的class
创建获取代理的通用接口:com.xpc.proxy.common.ProxyFactory
package com.xpc.proxy.common;
import com.xpc.proxy.common.consumer.Consumer;
public interface ProxyFactory {
/**
* 获取代理对象
*/
T getProxy(Class clazz);
}
JDK动态代理实现: com.xpc.rpc.proxy.jdk.JdkProxy
package com.xpc.rpc.proxy.jdk;
import com.xpc.proxy.common.ObjectProxy;
import com.xpc.proxy.common.ProxyFactory;
import com.xpc.proxy.common.consumer.Consumer;
import java.lang.reflect.Proxy;
public class JdkProxy implements ProxyFactory {
private Consumer consumer;
public JdkProxy(Consumer consumer) {
this.consumer = consumer;
}
//获取代理对象
@Override
public T getProxy(Class clazz) {
ClassLoader classLoader = clazz.getClassLoader();
Class[] interfaces = new Class[]{clazz};
return (T) Proxy.newProxyInstance(classLoader, interfaces, new ObjectProxy(consumer,clazz));
}
}
在 com.xpc.consumer.spring.scanner.reference.ReferenceScanner中,我们扫描到有成员变量被@DubboReference注解标记,那么我们就要为这个接口生成代理对象,并注入到这个变量中去
package com.xpc.consumer.spring.scanner.reference;
import com.xpc.consumer.spring.config.RpcConsumerAutoConfig;
import com.xpc.consumer.spring.scanner.ClassScanner;
import com.xpc.rpc.annotation.DubboReference;
import com.xpc.rpc.consumer.RpcConsumer;
import com.xpc.rpc.proxy.jdk.JdkProxy;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Field;
import java.util.List;
public class ReferenceScanner extends ClassScanner {
private static final Logger LOGGER = LoggerFactory.getLogger(ReferenceScanner.class);
public void doScanDubboReferenceByPackage(String packageName) throws Exception{
// 其它代码省略
classList.forEach(item -> {
try {
Class clazz = Class.forName(item);
Field[] clazzFields = clazz.getDeclaredFields();
for(Field field : clazzFields) {
DubboReference dubboReference = field.getAnnotation(DubboReference.class);
if(dubboReference != null) {
Class targetClazz = field.getType();
JdkProxy jdkProxy = new JdkProxy(RpcConsumer.getInstance());
//获取这个接口的代理对象
Object proxy = jdkProxy.getProxy(targetClazz);
//将代理对象设置到这个变量中去
setField(field, RpcConsumerAutoConfig.getObject(clazz),proxy,true);
}
}
} catch (Exception e) {
e.printStackTrace();
}
});
}
/**
* 设置类的属性值
*
* @param field 成员变量
* @param target 类实例
* @param value 成员变量的值
* @param accessible 是否允许设置私有属性
*/
public static void setField(Field field, Object target, Object value,boolean accessible){
try {
//是否允许设置私有的成员变量的值
field.setAccessible(accessible);
field.set(target,value);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}