spring-bean-proxy

87 阅读3分钟

动态代理

jdk-cglib

jdk

  • Proxy.newProxyInstance 通过interface创建代理类,interface.getMethods()能代理的方法
  • InvocationHandler 实现代理类执行的逻辑,被代理类作为field参数注入
  • 被代理类必须有interface

cglib

  • 通过继承被代理类,利用asm包,在子类通过回调实现代理
  • 被代理的方法和被代理的类不能是final,private修饰
  • MethodInterceptor 创建代理类的回调函数
  • Enhancer.create() 创建代理类
  • 类必须可以被继承,方法必须可以被继承

usage

  1. spring默认使用JDK
  2. springboot默认使用cglib
  3. spring加载时某些情况不会使用代理=> 没有理清楚
  4. dubbo代理使用Wapper

source-code

JDK

// 1. 创建接口的代理实例
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)throws IllegalArgumentException{
        // 代理逻辑不能为空
        Objects.requireNonNull(h);
        final Class<?>[] intfs = interfaces.clone();
        // 检查接口权限
        final SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
        }
        // 生成接口的代理类
        Class<?> cl = getProxyClass0(loader, intfs);
        try {
            if (sm != null) {
                checkNewProxyPermission(Reflection.getCallerClass(), cl);
            }
            // 代理类的构造方法 => 入参是invocationHandler对象
            final Constructor<?> cons = cl.getConstructor(constructorParams);
            final InvocationHandler ih = h;
            // 设置构造函数可以访问
            if (!Modifier.isPublic(cl.getModifiers())) {
                AccessController.doPrivileged(new PrivilegedAction<Void>() {
                    public Void run() {
                        cons.setAccessible(true);
                        return null;
                    }
                });
            }
            // 使用构造函数创建新的代理,并传入invocationHandler
            return cons.newInstance(new Object[]{h});
        } catch (IllegalAccessException|InstantiationException e) {
            throw new InternalError(e.toString(), e);
        } catch (InvocationTargetException e) {
            Throwable t = e.getCause();
            if (t instanceof RuntimeException) {throw (RuntimeException) t;} 
            else {throw new InternalError(t.toString(), t);}
        } catch (NoSuchMethodException e) {
            throw new InternalError(e.toString(), e);
        }
    }

// 2. 生成代理类的代码
private static Class<?> getProxyClass0(ClassLoader loader,Class<?>... interfaces) {
        if (interfaces.length > 65535) {
            throw new IllegalArgumentException("interface limit exceeded");
        }
        // 缓存,否则 ProxyClassFactory
        // If the proxy class defined by the given loader implementing
        // the given interfaces exists, this will simply return the cached copy;
        // otherwise, it will create the proxy class via the ProxyClassFactory
        return proxyClassCache.get(loader, interfaces);
    }

// 3.代理类工厂
 private static final class ProxyClassFactory implements BiFunction<ClassLoader, Class<?>[], Class<?>> {
        
        // 代理类的prefix
        private static final String proxyClassNamePrefix = "$Proxy";
        // 代理类的编号技术
        private static final AtomicLong nextUniqueNumber = new AtomicLong();

        @Override
        public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
            // 接口class集合
            Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
            for (Class<?> intf : interfaces) {
                Class<?> interfaceClass = null;
                try {
                    // 使用相同的loader获取接口class
                    interfaceClass = Class.forName(intf.getName(), false, loader);
                } catch (ClassNotFoundException e) {}
                if (interfaceClass != intf) {
                    // 接口不一致,在同一个classloader之下
                    throw new IllegalArgumentException(intf + " is not visible from class loader");
                }
                if (!interfaceClass.isInterface()) {
                    // 是否为接口
                    throw new IllegalArgumentException(interfaceClass.getName() + " is not an interface");
                }
                if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
                    // set去重
                    throw new IllegalArgumentException("repeated interface: " + interfaceClass.getName());
                }
            }
            String proxyPkg = null;     //  代理类的报名
            int accessFlags = Modifier.PUBLIC | Modifier.FINAL; //访问权限
            for (Class<?> intf : interfaces) {
                int flags = intf.getModifiers();
                if (!Modifier.isPublic(flags)) { 
                    // 非public的接口的包路径必须一致
                    accessFlags = Modifier.FINAL;
                    String name = intf.getName();
                    int n = name.lastIndexOf('.');
                    String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
                    if (proxyPkg == null) {
                        proxyPkg = pkg; //接口的包名
                    } else if (!pkg.equals(proxyPkg)) {
                        throw new IllegalArgumentException("non-public interfaces from different packages");
                    }
                }
            }
            // 默认包名
            if (proxyPkg == null) { 
                // if no non-public proxy interfaces, use com.sun.proxy package
                proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
            }
            // 代理类编号=>代理的类名:com.sun.proxy.$Proxy0
            long num = nextUniqueNumber.getAndIncrement();
            String proxyName = proxyPkg + proxyClassNamePrefix + num;
            // 生成代理类的字节码
            byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces, accessFlags);
            try {
                //字节码 => 生成class  
                return defineClass0(loader, proxyName,proxyClassFile, 0, proxyClassFile.length);
            } catch (ClassFormatError e) {
                throw new IllegalArgumentException(e.toString());
            }
        }
    }
// 4.  生成代理类的字节码
public static byte[] generateProxyClass(final String var0, Class<?>[] var1, int var2) {
        //初始化 并 生成字节码byte
        ProxyGenerator var3 = new ProxyGenerator(var0, var1, var2);
        final byte[] var4 = var3.generateClassFile();
        // 保存byte到字节码文件.class
        if (saveGeneratedFiles) {
            AccessController.doPrivileged(new PrivilegedAction<Void>() {
                public Void run() {
                    try {
                        // char(46) => .
                        int var1 = var0.lastIndexOf(46);
                        Path var2;
                        if (var1 > 0) {
                            // 文件目录 => com/sun/proxy/
                            Path var3 = Paths.get(var0.substring(0, var1).replace('.', File.separatorChar));
                            Files.createDirectories(var3);
                            // 文件名 => $Proxy0.class
                            var2 = var3.resolve(var0.substring(var1 + 1, var0.length()) + ".class");
                        } else {
                            var2 = Paths.get(var0 + ".class");
                        }
                        Files.write(var2, var4, new OpenOption[0]);
                        return null;
                    } catch (IOException var4x) {
                        throw new InternalError("I/O exception saving generated file: " + var4x);
                    }
                }
            });
        }
        return var4;
    }
// 5. 生成字节码
private byte[] generateClassFile() {
        // 增加object的代理方法
        this.addProxyMethod(hashCodeMethod, Object.class);
        this.addProxyMethod(equalsMethod, Object.class);
        this.addProxyMethod(toStringMethod, Object.class);
        
        Class[] var1 = this.interfaces;
        int var2 = var1.length;
        int var3;
        Class var4;
        // 增加所有接口的所有方法的代理
        for(var3 = 0; var3 < var2; ++var3) {
            var4 = var1[var3];
            //通过接口获取所有需要代理的方法
            Method[] var5 = var4.getMethods();
            int var6 = var5.length;
            for(int var7 = 0; var7 < var6; ++var7) {
                Method var8 = var5[var7];
                this.addProxyMethod(var8, var4);
            }
        }
        // 检查方法的return
        Iterator var11 = this.proxyMethods.values().iterator();
        List var12;
        while(var11.hasNext()) {
            var12 = (List)var11.next();
            checkReturnTypes(var12);
        }
        Iterator var15;
        try {
            // 添加构造
            this.methods.add(this.generateConstructor());
            var11 = this.proxyMethods.values().iterator(); // 代理方法
            while(var11.hasNext()) {
                var12 = (List)var11.next();
                var15 = var12.iterator();
                while(var15.hasNext()) {
                    // 代理方法
                    ProxyGenerator.ProxyMethod var16 = (ProxyGenerator.ProxyMethod)var15.next();
                    // 10 = private static 
                    this.fields.add(new ProxyGenerator.FieldInfo(var16.methodFieldName, "Ljava/lang/reflect/Method;", 10));
                    this.methods.add(var16.generateMethod());
                }
            }
            // static 初始化的代码块
            this.methods.add(this.generateStaticInitializer());
        } catch (IOException var10) {
            throw new InternalError("unexpected I/O Exception", var10);
        }
        if (this.methods.size() > 65535) {
            throw new IllegalArgumentException("method limit exceeded");
        } else if (this.fields.size() > 65535) {
            throw new IllegalArgumentException("field limit exceeded");
        } else {
            
            this.cp.getClass(dotToSlash(this.className));
            this.cp.getClass("java/lang/reflect/Proxy");
            var1 = this.interfaces;
            var2 = var1.length;
            for(var3 = 0; var3 < var2; ++var3) {
                var4 = var1[var3];
                this.cp.getClass(dotToSlash(var4.getName()));
            }
            this.cp.setReadOnly();
            ByteArrayOutputStream var13 = new ByteArrayOutputStream();
            DataOutputStream var14 = new DataOutputStream(var13);
            try {
                var14.writeInt(-889275714);
                var14.writeShort(0);
                var14.writeShort(49);
                this.cp.write(var14);
                var14.writeShort(this.accessFlags);
                var14.writeShort(this.cp.getClass(dotToSlash(this.className)));
                var14.writeShort(this.cp.getClass("java/lang/reflect/Proxy"));
                var14.writeShort(this.interfaces.length);
                Class[] var17 = this.interfaces;
                int var18 = var17.length;

                for(int var19 = 0; var19 < var18; ++var19) {
                    Class var22 = var17[var19];
                    var14.writeShort(this.cp.getClass(dotToSlash(var22.getName())));
                }
                var14.writeShort(this.fields.size());
                var15 = this.fields.iterator();

                while(var15.hasNext()) {
                    ProxyGenerator.FieldInfo var20 = (ProxyGenerator.FieldInfo)var15.next();
                    var20.write(var14);
                }

                var14.writeShort(this.methods.size());
                var15 = this.methods.iterator();

                while(var15.hasNext()) {
                    ProxyGenerator.MethodInfo var21 = (ProxyGenerator.MethodInfo)var15.next();
                    var21.write(var14);
                }
                var14.writeShort(0);
                return var13.toByteArray();
            } catch (IOException var9) {
                throw new InternalError("unexpected I/O Exception", var9);
            }
        }
    } 
// 6. 代理类模版(还需要重新反编译)
  public final class $Proxy0 extends Proxy implements Swimable {
      //变量,都是private static Method  XXX
      private static Method m3;  
      private static Method m1;
      private static Method m0;
      private static Method m2;
      //代理类的构造函数,其参数正是是InvocationHandler实例,Proxy.newInstance方法就是通过通过这个构造函数来创建代理实例的
      public $Proxy0(InvocationHandler var1) throws  {
          super(var1);
      }
      //接口代理方法
      public final void sayHello() throws  {
          try {
              // invoker-> object是原来的被代理对象
              super.h.invoke(this, m3, (Object[])null);
          } catch (RuntimeException | Error var2) {
              throw var2;
          } catch (Throwable var3) {
              throw new UndeclaredThrowableException(var3);
          }
      }
      //以下Object中的三个方法
      public final boolean equals(Object var1) throws  {
          try {
              return ((Boolean)super.h.invoke(this, m1, new Object[]{var1})).booleanValue();
          } catch (RuntimeException | Error var3) {
              throw var3;
          } catch (Throwable var4) {
              throw new UndeclaredThrowableException(var4);
          }
      }
      public final int hashCode() throws  {
          try {
              return ((Integer)super.h.invoke(this, m0, (Object[])null)).intValue();
          } catch (RuntimeException | Error var2) {
              throw var2;
          } catch (Throwable var3) {
              throw new UndeclaredThrowableException(var3);
          }
      }
      public final String toString() throws  {
          try {
              return (String)super.h.invoke(this, m2, (Object[])null);
          } catch (RuntimeException | Error var2) {
              throw var2;
          } catch (Throwable var3) {
              throw new UndeclaredThrowableException(var3);
          }
      }
      //对变量进行一些初始化工作
      static {
          try {
              m3 = Class.forName("com.mobin.proxy.IHello").getMethod("sayHello", new Class[0]);
              m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")});
              m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
              m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
          } catch (NoSuchMethodException var2) {
              throw new NoSuchMethodError(var2.getMessage());
          } catch (ClassNotFoundException var3) {
              throw new NoClassDefFoundError(var3.getMessage());
          }
      }
  }    

CGlib

// 1. 创建,被代理类必须可以被继承,被代理的方法必须可以被继承
public static Object create(Class type, Callback callback) {
        Enhancer e = new Enhancer();
        // 指定父类,继承被代理的对象
        e.setSuperclass(type);
        // 指定回调函数,代理类调用时执行
        e.setCallback(callback);
        return e.create();
    }
// 2. ....
// 3. 代理类模版