• 【无标题】


    在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
  • 相关阅读:
    配置web服务器+编写简单页面+分析交互过程
    三层vlan实验
    EBS R12.2.0升级到R12.2.6
    Instagram 早期技术架构
    判断二叉树是否为二叉搜索树
    【AWS】如何用SSH连接aws上的EC2实例(虚拟机)?
    2023年天津仁爱学院专升本动画专业报考专业限制范围目录
    笔记(二)图的基本表示【斯坦福CS224W图机器学习】
    java毕业设计——基于java+Jsoup+HttpClient的网络爬虫技术的网络新闻分析系统设计与实现——网络新闻分析系统
    java计算机毕业设计流浪动物救助公益平台源码+系统+数据库+lw文档+mybatis+运行部署
  • 原文地址:https://blog.csdn.net/qq_45372719/article/details/134424510