天天看点

手把手实现RPC框架--简易版Dubbo构造(三)客户端动态代理

本节commit源码地址:416bb92

客户端实现(动态代理)

由于在客户端这边我们并没有接口的具体实现类,就没有办法直接生成实例对象。这时,我们可以通过JDK动态代理的方式生成实例。(关于动态代理不太熟的小伙伴可以戳:动态代理详解)

public class RpcClientProxy implements InvocationHandler {

    private String host;
    private int port;
    
    //传递host和port来指明服务端的位置
    public RpcClientProxy(String host, int port){
        this.host = host;
        this.port = port;
    }

    //抑制编译器产生警告信息
    @SuppressWarnings("unchecked")
    public <T> T getProxy(Class<T> clazz){
        //创建代理对象
        return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class<?>[]{clazz}, this);
    }
}
           

InvocationHandler

接口需要实现invoke()方法,来指明代理对象的方法被调用时的动作。在这里,我们显然就需要生成一个RpcRequest对象,发送出去,然后把从服务端返回的结果return即可。

@Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //客户端向服务端传输的对象,Builder模式生成
        RpcRequest rpcRequest = RpcRequest.builder()
                .interfaceName(method.getDeclaringClass().getName())
                .methodName(method.getName())
                .parameters(args)
                .paramTypes(method.getParameterTypes())
                .build();
        //进行远程调用的客户端
        RpcClient rpcClient = new RpcClient();
        return ((RpcResponse)rpcClient.sendRequest(rpcRequest, host, port)).getData();
    }
           

Builder设计模式学习参考:https://blog.csdn.net/qq_38685503/article/details/113620036

具体的远程api调用逻辑利用RpcClient对象来实现,这个对象的作用,就是将一个对象发过去,并且接受返回的对象。

public class RpcClient {

    private static final Logger logger = LoggerFactory.getLogger(RpcClient.class);

    public Object sendRequest(RpcRequest rpcRequest, String host, int port) {
        /**
         * socket套接字实现TCP网络传输
         * try()中一般放对资源的申请,若{}出现异常,()资源会自动关闭
         */
        try (Socket socket = new Socket(host, port)) {
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
            ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
            objectOutputStream.writeObject(rpcRequest);
            objectOutputStream.flush();
            return objectInputStream.readObject();
        } catch (IOException | ClassNotFoundException e) {
            logger.error("调用时有错误发生:" + e);
            return null;
        }
    }
}
           

上面就是直接使用Java的序列化方式,通过Socket传输。创建一个Socket,获取ObjectOutputStream对象,然后把需要发送的对象传进去即可,接收时获取ObjectInputStream对象,readObject()方法就可以获得一个返回的对象。Socket原理如图:

手把手实现RPC框架--简易版Dubbo构造(三)客户端动态代理

本节结束……