1. 动静代理调用流程

RPC的调用对用户来讲是通明的,外部具体是如何实现呢?

核心技术采纳的就是动静代理,RPC 会主动给接口生成一个代理类,当咱们在我的项目中注入初始化接口的时候,运行过程中理论绑定的是这个接口生成的代理类。
在接口办法被调用的时候,它实际上是被生成代理类拦挡到了,这样就能够在生成的代理类外面,退出其余调用解决逻辑。

2. 为什么要退出动静代理

  1. 如果没有动静代理, 服务端大量的接口将不便于管理,须要大量的if判断,如果扩大了新的接口,须要更改调用逻辑, 不利于扩大保护。
  2. 动静代理能够做到外部办法级拦挡,并且增加其余额定性能, 比方连贯负载治理,权限管制,日志记录等等。

3. JDK动静代理实现

  1. JDK动静代理实现流程:
  2. 实现代码:

      public class JDKDynamicProxy {         public static void main(String[] args){                 // 构建代理器                 JDKProxy proxy = new JDKProxy(new Teacher());                 ClassLoader classLoader = JDKDynamicProxy.class.getClassLoader();                 // 生成代理类                 User user = (User) Proxy.newProxyInstance(classLoader, new Class[]{User.class}, proxy);                 // 接口调用                 System.out.println(user.job());         }         /**          * 定义用户的接口          */         public interface User {                 String job();         }         /**          * 理论的调用对象          */         public static class Teacher  {                 public String invoke(){                         return "i'm a Teacher";                 }         }         /**          * 创立JDK动静代理类          */         public static class JDKProxy implements InvocationHandler {                 private Object target;                 JDKProxy(Object target) {                         this.target = target;                 }                 @Override                 public Object invoke(Object proxy, Method method, Object[] paramValues) {                         return ((Teacher)target).invoke();                 }         } }

反编译生成的代理类能够晓得,代理类 $Proxy外面会定义雷同签名的接口(也就是下面代码User的job接口),而后外部会定义一个变量绑定JDKProxy代理对象,当调用User.job接口办法,本质上调用的是JDKProxy.invoke()办法,从而实现了接口的动静代理。

4. Cglib动静代理实现

  1. 服务接口

    编写订单服务的下单接口:
      public class OrderService {    /**     * 下单接口     */    public String placeOrder(String userName) {        System.out.println("用户:" + userName + "开始下单");        return "胜利";    }}
  2. 代理实现

     实现MethodInterceptor接口, 重写intercept办法, 能够追加校验逻辑、日志记录等性能。
    public class OrderServiceCglib implements MethodInterceptor {    public Object getProxy(Object target) {        Enhancer enhancer = new Enhancer();        enhancer.setSuperclass(target.getClass());        // 设置回调办法        enhancer.setCallback(this);        // 创立代理对象        return enhancer.create();    }    /**     * 实现MethodInterceptor接口中重写的办法     */    @Override    public Object intercept(Object object, Method method, Object[] args, MethodProxy proxy) throws Throwable {        System.out.println("校验下单参数:" + Arrays.asList(args));        Object result = proxy.invokeSuper(object, args);        System.out.println("记录下单日志后果: " + result);        return result;    }}

5. 开源动静代理技术解析

(1) Cglib 动静代理

Cglib是一个弱小的、高性能的代码生成包,它宽泛被许多AOP框架应用,反对办法级别的拦挡。它是高级的字节码生成库,位于ASM之上,ASM是低级的字节码生成工具,ASM的应用对开发人员要求较高,相比拟来讲, ASM性能更好。

(2) Byte Buddy 字节码加强库

Byte Buddy是致力于解决字节码操作和 简化操作复杂性的开源框架。Byte Buddy 指标是将显式的字节码操作暗藏在一个类型平安的畛域特定语言背地。它属于后起之秀,在很多优良的我的项目中,像 Spring、Jackson 都用到了 Byte Buddy 来实现底层代理。相比 Javassist,Byte Buddy 提供了更容易操作的 API,编写的代码可读性更高。

(3) Javassist 动静代理

一个开源的剖析、编辑和创立Java字节码的类库。javassist是jboss的一个子项目,它间接应用java编码的模式,不须要理解虚拟机指令,能够动静扭转类的构造,或者动静生成类。Javassist 的定位是可能操纵底层字节码,所以应用起来并不简略,Dubbo 框架的设计者为了谋求性能破费了不少精力去适配javassist。

6. 开源动静代理性能比拟

Byte Buddy、 CGLIB、 Javassist、 JDK动静代理性能比拟:

综合后果:

单位是纳秒。大括号内代表的是样本标准差,综合后果:Byte Buddy > CGLIB > Javassist> JDK。

7. Dubbo动静代理源码分析

  1. 源码调用流程
  2. 外围源码:
本文由mirson创作, 心愿对大家有所帮忙, 谢谢!