Skip to content

Instantly share code, notes, and snippets.

@ruan4261
Last active February 19, 2021 09:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ruan4261/fd1fbb5201841d34c35a896b7b987b70 to your computer and use it in GitHub Desktop.
Save ruan4261/fd1fbb5201841d34c35a896b7b987b70 to your computer and use it in GitHub Desktop.

一个ProxyGenerator实例代表一个代理类

ProxyGenerator实例中重要的属性

  /** 保存所有接口的方法, key为方法签名, value中位不同返回值的同签名方法 */
  Map<String, List<ProxyMethod>> proxyMethods;
  
  /** 保存最终的字段信息, 每一个元素会生成一个实例字段 */
  List<FieldInfo> fields;
  /** 保存最终的方法信息, 每一个元素会生成一个实例方法 */
  List<MethodInfo> methods;
  1. #generateClassFile()

    生成入口, 返回代理类字节码
    步骤

    1. 通过#addProxyMethod(Method, Class)注册hashCode, equals, toString方法
    2. 通过#addProxyMethod(Method, Class)循环注册每个接口的每个方法
    3. 对所有注册方法的返回值进行最终校验
    4. 通过#generateConstructor()将构造方法添加到最终信息区
    5. 遍历#proxyMethods, 将每一个ProxyMethod转变为一个FieldInfo及一个MethodInfo
    6. 通过#generateStaticInitializer()将静态代码块添加到最终信息区
  2. #generateStaticInitializer()

    代理类的静态代码块static{}, 该代码块会注册每个方法的原生引用

  3. #generateConstructor()

    代理类的构造方法, 此处会调用父类的构造, 该构造及父构造都拥有一个参数InvocationHandler

  4. $ProxyMethod#codeFieldInitialization(DataOutputStream out)

    调用方: #generateStaticInitializer()
    用于生成获取原生方法引用的字节码(Class.forName(...).getMethod(...))

  5. $ProxyMethod#generateMethod()

    调用方: #generateClassFile()
    用于生成代理类的方法主体

  6. #addProxyMethod(Method, Class)

    向实例属性#proxyMethods注册方法签名.
    如果方法签名已添加(不同类的同签名方法), 则判断返回值.
    如果返回值完全相同, 将其合并, 异常集将取两方法异常集的交集.
    如果返回值不相同, 添加到同一个Entry中, 等待后续校验.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment