• 【无标题】


    在RPC中使用JDK动态代理

    1.什么是动态代理

    动态代理简单来说,就是在你需要用到某个类的时候,由Proxy给你动态构建这个类,同时你可以根据自己的需求定制具体方法的实现。
    它可以在运行时动态实现接口,不仅可以有效解耦,还能实现很多操作,比如混淆编译,即编译的时候在代码中混淆一些东西,防止别人反编译,;另一个就是方法拦截器,这个可操作性也很大,比如AOP、日志记录等。

    2.简单的JDK动态代理实现

    由于本次主要记录一下在RPC中使用jdk动态代理,所以这里简单介绍一下。

    2.1 创建代理接口ProxyService:

    
    public interface ProxyService {	
        void proxyMethod();	
    }
    
    • 1
    • 2
    • 3
    • 4

    2.2 创建接口实现类ProxyServiceImpl

    public class ProxyServiceImpl implements ProxyService {
        @Override
        public void proxyMethod() {
            System.out.println("ProxyService.proxyMethod() running");
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2.3 创建InvocationHandler接口的实现类

    public class MyInvocationHandler implements InvocationHandler {
    
        private Object target;
    
        public MyInvocationHandler(Object target){
            this.target = target;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable {
            System.out.println("MyInvocationHandler.invoke 方法开始");
            method.invoke(target, args);
            System.out.println("MyInvocationHandler.invoke 方法结束");
            return null;
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    2.4 测试动态代理

    public class JavaProxyTest {
    
        public static void main(String[] args) {
            MyInvocationHandler handler = new MyInvocationHandler(new ProxyServiceImpl()); //被代理的对象
            ProxyService proxyService = (ProxyService) Proxy.newProxyInstance(JavaProxyTest.class.getClassLoader(), new Class[] { ProxyService.class }, handler);//代理对象
            proxyService.proxyMethod();  
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    2.5 结果

    image.png

    3. RPC中使用动态代理

    在RPC中,由于消费者和服务者在不同的服务器中,所以方法的执行是中服务端中进行的,在发送端的代理方法中,我们发送方法名、接口名、参数类型、具体的参数,在服务端中收到这些参数再执行具体的方法。

    3.1 发送端代码

    • 被代理的接口(实现中服务端)
    public interface HelloService {
        String hello(Hello hello);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 执行发送
    HelloService helloServiceProxy = rpcClientProxy.getProxy(HelloService.class);//代理对象
    String sendData = helloServiceProxy.hello(new Hello("111", "send data"));
    System.out.println(sendData);
    
    • 1
    • 2
    • 3
    • 代理逻辑
    public Object invoke(Object o, Method method, Object[] args) throws Throwable {
            log.info("invoked method {}",method.getName());
            RpcRequest rpcRequest = RpcRequest.builder().methodName(method.getName())
                    .parameters(args)
                    .interfaceName(method.getDeclaringClass().getName())
                    .paramTypes(method.getParameterTypes())
                    .requestId(UUID.randomUUID().toString())
                    .build();
    
            //send
    		sendRpcRequest(rpcRequest);
            return "send successful";
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    3.2 服务端代码

    • 提供服务
    @Slf4j
    public class HelloServiceImpl2 implements HelloService {
    
        static {
            System.out.println("HelloServiceImpl2被创建");
        }
    
        @Override
        public String hello(Hello hello) {
            log.info("HelloServiceImpl2收到: {}.", hello.getMessage());
            String result = "Hello description is " + hello.getDescription();
            log.info("HelloServiceImpl2返回: {}.", result);
            return result;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 发布服务
    HelloService helloServiceImpl2 = new HelloServiceImpl2();
    RpcServiceConfig rpcServiceConfig = RpcServiceConfig.builder().group("test").version("version2").service(helloServiceImpl2).build();
    nettyServer.registerService(rpcServiceConfig);
    
    • 1
    • 2
    • 3
    • 服务端解析受到的参数,并通过反射执行具体的方法
    public Object invokeTargetMethod(RpcRequest rpcRequest) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        String rpcServiceName = rpcRequest.getRpcServiceName();
        Object service = serviceProvider.getService(rpcServiceName);//获得实际对象
        Method method = service.getClass().getMethod(rpcRequest.getMethodName(), rpcRequest.getParamTypes());
        Object invoke = method.invoke(service, rpcRequest.getParameters());
        return invoke;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
  • 相关阅读:
    HashMap深入底层源码思考问题
    Linux 爱好者线下沙龙:成都场圆满结束 & 下一场西子湖畔相见 | LLUG·第五站
    【1993. 树上的操作】
    洛谷2022SCP第一轮J组模拟题(LGR-2022-J1)部分题解
    VMware Ubuntu 关闭自动更新
    KVM导入Ubuntu Cloud 镜像创建虚机及调整磁盘大小
    JumpServer 堡垒机 v2.25.0 发布
    Matplotlib入门[04]——处理图像
    港联证券:“保险+期货”快速落地生花 涉及品种累计达18个
    【历史上的今天】8 月 15 日:苹果推出初代 iMac;谷歌收购摩托罗拉移动;Fuchsia 首次发布
  • 原文地址:https://blog.csdn.net/qq_45372719/article/details/134424510