手写RPC框架(十六)

v2.7

更新:实现CGLIB动态代理

  • 实现CGLIB动态代理

    • 实现一下统一调用代理类,创建总调用类,和对应模板接口,调用注解,同时在每个consumerbootstrap进行修改

      • 对应模板接口

        package consumer.proxy;
        
        //模板
        public interface ClientProxy {
            public  Object getBean(final Class<?> serviceClass);
        }
        
      • 总调用类(通过SPI机制进行调用) //用户千万要注意当你选用的是nio的话千万只能用nio的方法

        • SPI机制对应配置 存放实现类的全限定名和实现类
          在这里插入图片描述

        • SPI工具箱

          package consumer.proxy;
          
          import exception.RpcException;
          
          import java.util.ServiceLoader;
          
          public class SPIClientProxyUtils {
              public static ClientProxy getUtils() throws RpcException {
                  ServiceLoader<ClientProxy> loader = ServiceLoader.load(ClientProxy.class);
                  for (ClientProxy clientProxy : loader) {
                      return clientProxy;
                  }
                  throw new RpcException("您键入的代理,并未实现,欢迎实现提出pr");
              }
          }
          
    • 实现CGLIB动态代理

      • 依赖引入

        <!--CGLIB依赖引入-->
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>3.3.0</version>
        </dependency>
        
      • 构建代理类实现代码

        package consumer.proxy.netty;
        
        import annotation.RegistryChosen;
        import consumer.netty.NettyClient;
        import consumer.proxy.ClientProxy;
        import consumer.service_discovery.NacosServiceDiscovery;
        import consumer.service_discovery.ZkCuratorDiscovery;
        import consumer.service_discovery.ZkServiceDiscovery;
        import exception.RpcException;
        import net.sf.cglib.proxy.Enhancer;
        import net.sf.cglib.proxy.MethodInterceptor;
        import net.sf.cglib.proxy.MethodProxy;
        import register.Register;
        
        import java.lang.reflect.Method;
        
        //Cglib实现代理模式
        public class RpcNettyClientCGLIBProxy implements ClientProxy,MethodInterceptor{
        
            @Override
            public Object getBean(Class serviceClass) {
                //设置动态代理增强类
                Enhancer enhancer = new Enhancer();
                //设置类加载器
                // enhancer.setClassLoader(serviceClass.getClassLoader());
                //设置代理类
                enhancer.setSuperclass(serviceClass);
                //设置对应的方法执行拦截器,方法回调
                enhancer.setCallback(this);
        
                return enhancer.create();
            }
        
            /**
             * @param obj           代理对象(增强的对象)
             * @param method      被拦截的方法(需要增强的方法)
             * @param args        方法入参
             * @param methodProxy 用于调用原始方法
             */
            @Override //自定义对应的拦截 拦截方法并执行别的任务
            public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                String methodAddress = getMethodAddress(method.getName());
                String[] split = methodAddress.split(":");
                return NettyClient.callMethod(split[0],Integer.valueOf(split[1]),args[0],method);
            }
        
        
        
        
            /**
             * 实际去获得对应的服务 并完成方法调用的方法
             * @param methodName  根据方法名  根据添加的注册中心注解来选择相应的注册中心进行  实现负载均衡获取一个方法对应地址
             * @param
             * @return
             */
            private static String getMethodAddress(String methodName) throws Exception {
                //根据注解进行方法调用
                //根据在代理类上的注解调用  看清楚底下的因为是个class数组 可以直接继续获取 注解
                RegistryChosen annotation = Register.class.getAnnotation(RegistryChosen.class);
                switch (annotation.registryName())
                {
                    case "nacos":
                        return NacosServiceDiscovery.getMethodAddress(methodName);
                    case "zookeeper":
                        return ZkServiceDiscovery.getMethodAddress(methodName);
                    case "zkCurator":
                        return ZkCuratorDiscovery.getMethodAddress(methodName);
                    default:
                        throw new RpcException("不存在该注册中心");
                }
            }
        }
        
    • BUG

      • 问题
        在这里插入图片描述

      • 解决
        追进去看CGLIB构建代理类源码 是什么原因造成的这个错误,同时别人也是可以代理接口的啊
        JDK动态代理代理接口,cglib可以代理类和接口

        1. 经过验证 应该是和我们传进去的方法无关的
        2. 找到错误了 进行创建应该是enhancer.create()方法 我给写成了enhancer.createClass()
  • 问题声明
    在调用方法这边这么写的原因是,无法获取对应调用类上的版本信息,会导致循环依赖,如果读者想更简单调用每个版本都对应一个对应的NettyClient的类 可以直接通过对应的NettyClient进行调用

    在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值