• java动态代理ProxyGenerator


      jdk自带实现动态代理核心逻辑即是在调用  java.lang.reflect.Proxy#newProxyInstance 时,根据用户指定实现的接口动态创建一个Proxy类定义的byte[],然后调用native 的defineClass返回该代理类的实例;

    核心逻辑实例:

     1 String className = "com.sun.$Proxy";
     2         int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
     3 
     4         Class<?>[] cls = new Class<?>[]{Executor.class};
     5 
     6         byte[] bytes = ProxyGenerator.generateProxyClass(className, cls, accessFlags);
     7         
     8         System.out.println("byteLen: " + bytes.length);
     9         Path path = Paths.get("D:\misc\Proxy.class");
    10 
    11         try {
    12             Files.createFile(path);
    13             OutputStream outputStream = Files.newOutputStream(path, StandardOpenOption.WRITE);
    14             outputStream.write(bytes);
    15             outputStream.close();
    16         } catch (IOException e) {
    17             e.printStackTrace();
    18         }

    这里将byte[] 写入文件,二进制文件Proxy.class 反编译后类似:

     1 //
     2 // Source code recreated from a .class file by IntelliJ IDEA
     3 // (powered by Fernflower decompiler)
     4 //
     5 
     6 package com.sun;
     7 
     8 import indi.joynic.actscase.gen.aopalliance.Executor;
     9 import java.lang.reflect.InvocationHandler;
    10 import java.lang.reflect.Method;
    11 import java.lang.reflect.Proxy;
    12 import java.lang.reflect.UndeclaredThrowableException;
    13 
    14 public final class $Proxy extends Proxy implements Executor {
    15     private static Method m1;
    16     private static Method m2;
    17     private static Method m3;
    18     private static Method m0;
    19 
    20     public $Proxy(InvocationHandler var1) throws  {
    21         super(var1);
    22     }
    23 
    24     public final boolean equals(Object var1) throws  {
    25         try {
    26             return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
    27         } catch (RuntimeException | Error var3) {
    28             throw var3;
    29         } catch (Throwable var4) {
    30             throw new UndeclaredThrowableException(var4);
    31         }
    32     }
    33 
    34     public final String toString() throws  {
    35         try {
    36             return (String)super.h.invoke(this, m2, (Object[])null);
    37         } catch (RuntimeException | Error var2) {
    38             throw var2;
    39         } catch (Throwable var3) {
    40             throw new UndeclaredThrowableException(var3);
    41         }
    42     }
    43 
    44     public final char execute() throws  {
    45         try {
    46             return (Character)super.h.invoke(this, m3, (Object[])null);
    47         } catch (RuntimeException | Error var2) {
    48             throw var2;
    49         } catch (Throwable var3) {
    50             throw new UndeclaredThrowableException(var3);
    51         }
    52     }
    53 
    54     public final int hashCode() throws  {
    55         try {
    56             return (Integer)super.h.invoke(this, m0, (Object[])null);
    57         } catch (RuntimeException | Error var2) {
    58             throw var2;
    59         } catch (Throwable var3) {
    60             throw new UndeclaredThrowableException(var3);
    61         }
    62     }
    63 
    64     static {
    65         try {
    66             m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
    67             m2 = Class.forName("java.lang.Object").getMethod("toString");
    68             m3 = Class.forName("indi.joynic.actscase.gen.aopalliance.Executor").getMethod("execute");
    69             m0 = Class.forName("java.lang.Object").getMethod("hashCode");
    70         } catch (NoSuchMethodException var2) {
    71             throw new NoSuchMethodError(var2.getMessage());
    72         } catch (ClassNotFoundException var3) {
    73             throw new NoClassDefFoundError(var3.getMessage());
    74         }
    75     }
    76 }

    生成了一个新的Proxy代理子类,可以看到实际返回的类定义写入了 hashCode() 、toString()、equals()和 用户接口方法 execute(), 而且将方法调用委派给用户指定的 InvocationHandler。

    所以本质上来说“动态代理”仍旧是“静态代理”,“动态”表现在不用修改代码的情况下运行时通过“魔改”,然后“偷梁换柱”的方式返回给用户代理对象;

    对用户来说,调用返回的代理对象本身就实现了用户接口 (implements Executor)。

    从用户的角度语义上讲即为:“塞给java.lang.reflect.Proxy任意接口和目标对象,Poxy都能给出用户指定增强目标对象接口方法逻辑的代理对象”;

    如果不制定具体是哪个接口java.lang.reflect.Proxy 无法得知在从何处抽取出接口方法生成class byte数组。

    无接口AOP增强类方法就要依靠cglib之类工具了。

  • 相关阅读:
    JQuery对象操作支持链式法则源码分析
    JQuery + JSON作为前后台数据交换格式实践
    JQuery html API支持解析执行Javascript脚本功能实现-代码分析
    跨域访问实践
    XP下安装MAC OS虚拟系统
    Android APP开发笔记
    CSS浮动与清浮动
    LUA 模块化编程例子
    JavaScript解决命名冲突的一种方法
    XML中文本节点存储任意字符的方法
  • 原文地址:https://www.cnblogs.com/Joynic/p/13741473.html
Copyright © 2020-2023  润新知