RPC实战与核心原理之动态代理了

动态代理

回顾

用来解决两个应用之间的通信,而网络则是两台l两台机器之间的“桥梁”,只有搭好桥梁才能把请求数据从一端传输到另一端,其中关键就是“可靠的传输”

背景

RPC的目标就是通过屏蔽调用细节,实现远程调用如同本地调用一样简单

在使用RPC时,一般的做法是先找服务提供方要接口,通过Maven或者其他工具把接口依赖到项目中,通过依赖注入的方式把接口注入项目中,然后在代码里面直接调用的方法

核心技术:动态代理

  • RPC会自动给接口生成一个代理类,在项目中注入接口的时候,运行过程中实际绑定的是这个接口生成的代理类,在接口方法被调用的时候,实际上是被生成代理类拦截到了,这样就可以在生成的代理类中加入远程调用逻辑

动态代理

实现原理

/**

  • 要代理的接口
    */
    public interface Hello {
      String say();
    }

/**

  • 真实调用对象
    */
    public class RealHello {

public String invoke(){
    return "i'm proxy";
  }
}

/**

  • JDK代理类生成
    */
    public class JDKProxy implements InvocationHandler {
      private Object target;

JDKProxy(Object target) {
    this.target = target;
  }

@Override
  public Object invoke(Object proxy, Method method, Object[] paramValues) {
    return ((RealHello)target).invoke();
  }
}

/**

  • 测试例子
    */
    public class TestProxy {

public static void main(String[] args){
    // 构建代理器
    JDKProxy proxy = new JDKProxy(new RealHello());
    ClassLoader classLoader = ClassLoaderUtils.getCurrentClassLoader();
    // 把生成的代理类保存到文件
System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
    // 生成代理类
    Hello test = (Hello) Proxy.newProxyInstance(classLoader, new Class[]{Hello.class}, proxy);
    // 方法调用
    System.out.println(test.say());
  }
}

  • 给Hello接口生成一个动态代理类,并调用接口say()方法,但真实返回的值是来自RealHello里面的invoke()方法返回值

实现方法

  • 在java领域(而我对java不熟),除了JDK默认的nvocationHandler能完成代理,还有很多第三方框架,如javassist、BYTE Buddy这样的框架也行

动态代理是一种具体的技术框架,那就会涉及到选型的问题,可从以下考虑

  • 因为代理类是在运行中生成的,那么代理框架生成代理类的速度、生成代理类的字节码大小等等,都会影响到其性能——生成的字节码越小,运行所占资源就越小。
  • 还有就是我们生成的代理类,是用于接口方法请求拦截的,所以每次调用接口方法的时候,都会执行生成的代理类,这时生成的代理类的执行效率就需要很高效。
  • 最后一个是从我们的使用角度出发的,我们肯定希望选择一个使用起来很方便的代理类框架,比如我们可以考虑:API 设计是否好理解、社区活跃度、还有就是依赖复杂度等等。
posted @ 2022-02-13 17:10  牛犁heart  阅读(377)  评论(0编辑  收藏  举报