JDK和CGLB动态代理机制分析

JDK动态的代理:

https://blog.csdn.net/P19777/article/details/103998918

先来一个大致的机制介绍,后面是详细的:
生成一个代理类实现了被代理类的接口,代理类实现目标方法,方法中会调用InvocationHandler 实现类的invoke方法;

大家都会的无脑使用方式,简单写个demo

1、定义一个接口:

package com.bijian.proxy;

public interface UserService {
   void update();
}

2、定义一个实现 类
package com.bijian.proxy;


public class UserServiceImpl implements UserService {
   @Override
   public void update() {
      System.out.println("执行目标方法...");
   }
}

3、定义一个动态代理生产的类:这也是最重要的

package com.bijian.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JDKProxy  implements InvocationHandler {
   /**
    * 目标类
    */
   private Object target;

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

   @Override
   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      System.out.println("JDK动态代理前置通知 method=" + method.getName() + " args=" + args);
      Object invoke = method.invoke(target, args);
      System.out.println("JDK动态代理后置通知method=" + method.getName() + " args=" + args);
      return invoke;
   }

   public Object getProxy() {
      return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
   }


   public static void main(String[] args) {
      System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
      JDKProxy proxy = new JDKProxy(new UserServiceImpl());
      UserService userService =(UserService) proxy.getProxy();
      userService.update();
   }
}

机制分析

生成一个代理类,这个代理类实现了被代理类的接口;重写了其增强的方法,以上面的demo为例,会重写其update方法;接下来直接上生成的代理类代码:

package com.sun.proxy;

import com.bijian.proxy.UserService;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class $Proxy0 extends Proxy implements UserService {
    private static Method m1;
    private static Method m2;
    private static Method m0;
    private static Method m3;

    public $Proxy0(InvocationHandler var1) throws  {
        super(var1);
    }

    public final boolean equals(Object var1) throws  {
        try {
            return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    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);
        }
    }

    public final int hashCode() throws  {
        try {
            return (Integer)super.h.invoke(this, m0, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final void update() throws  {
        try {
            super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
            m3 = Class.forName("com.bijian.proxy.UserService").getMethod("update");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

这一步获取的生成的代理对象也就是UserService userService =(UserService) proxy.getProxy();
点开源码,其中这一步 Class<?> cl = getProxyClass0(loader, intfs);就是生成代理类的class文件和class对象的;传参为被代理对象的类加载器和接口的class对象,返回代理类的class对象,然后cons.newInstance(new Object[]{h})利用反射技术创建代理类对象,传参为我们实现了 InvocationHandler接口的JDKProxy 对象;

当执行userService.update();方法时其实是执行的是代理类中的方法:

public final void update() throws  {
        try {
            super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

其中super.h.invoke(this, m3, (Object[])null);也就是调用JDKProxy 中重写的方法:

   @Override
   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      System.out.println("JDK动态代理前置通知 method=" + method.getName() + " args=" + args);
      Object invoke = method.invoke(target, args);
      System.out.println("JDK动态代理后置通知method=" + method.getName() + " args=" + args);
      return invoke;
   }

传参为:第一参数为当前代理对象,第二个参数为目标方法对象,第三个参数为目标方法的参数数组对象;因为执行目标方法使用反射技术执行的,所以效率没有CGLB代理的高。

接着进入创建代理对象的的方法中:
Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);

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);
    }

    /*
     * Look up or generate the designated proxy class.
     */

    Class<?> cl = getProxyClass0(loader, intfs);

    /*
     * Invoke its constructor with the designated invocation handler.
     */
    try {
        if (sm != null) {
            checkNewProxyPermission(Reflection.getCallerClass(), cl);
        }

        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;
                }
            });
        }
        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);
    }
}

CGLB动态代理:

概述:动态代理是生成一个代理类继承被代理类,重写其每个方法;通过获取代理类来调用代理类中重写了目标方法的方法;

先上一个小白就会写的demo:

被代理类

package com.bijian.proxy;

import org.springframework.cglib.core.DebuggingClassWriter;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 *     jdk代理:
 *     会生成
 *     这里非常坑的是invoke方法和invokeSuper的区别,
 *     如果是用invoke方法一定要使用被代理的对象也就是上文中的target,
 *     而如果调用invokeSuper方法,则一定要使用被代理后的o对象。
*后面从源码角度分析
 */
public class CglibProxy implements MethodInterceptor {
   private Object target;

   public CglibProxy(Object target) {
      this.target = target;
   }

   @Override
   public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
      System.out.println("CGLP代理方面名=" + method.getName() + "前置通知");
      Object invoke = methodProxy.invokeSuper(o, objects);
      System.out.println("CGLP代理方面名=" + method.getName() + "后置通知");
      return invoke;
   }

   public Object getProxy() {
      Enhancer enhancer = new Enhancer();
      enhancer.setCallback(this);
      enhancer.setSuperclass(this.target.getClass());
      return enhancer.create();
   }

   public static void main(String[] args) {
      System.getProperties().put(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,"D:\\workspace\\spring-ioc-demo\\spring-framework-5.2.9.RELEASE\\my-spring-test\\src\\main\\java\\com\\bijian\\proxy");
      CglibProxy cglibProxy = new CglibProxy(new UserServiceImpl());
      UserService userServiceProxy =(UserService) cglibProxy.getProxy();
      userServiceProxy.update();

   }
}

机制分析:
在执行main方法时会生成三个代理类:
在这里插入图片描述
这三个类是enhancer.create()这一步产生的,我也没有具体看里面的代码

FastClass机制
Jdk动态代理的拦截对象是通过反射的机制来调用被拦截实例方法的,反射的效率比较低,所以cglib采用了FastClass的机制来实现对被拦截方法的调用。FastClass机制就是对一个类的方法建立索引,调用方法时根据方法的签名来计算索引,通过索引来直接调用相应的方法

生成的代理类介绍:
图片中中间的是生成的代理类,另外两个类是为代理类和原始类生成的fastClass机制的类;都是继承了FastClass这个类,其中一个是为生成的代理类中每个方法建立了索引,另一个类是为被代理类中每个方法建立了索引。

先看一下被代理类FastClass机制类:
有一个通过方法签名获得方法索引的方法;
还有一个通过索引和被代理对象和方法参数,执行目标方法的方法

package com.bijian.proxy;

import java.lang.reflect.InvocationTargetException;
import org.springframework.cglib.core.Signature;
import org.springframework.cglib.reflect.FastClass;

public class UserServiceImpl$$FastClassByCGLIB$$ff2de1c extends FastClass {
    public UserServiceImpl$$FastClassByCGLIB$$ff2de1c(Class var1) {
        super(var1);
    }

    public int getIndex(Signature var1) {
        String var10000 = var1.toString();
        switch(var10000.hashCode()) {
        case -1949253108:
            if (var10000.equals("update()V")) {
                return 0;
            }
            break;
        case 1826985398:
            if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
                return 1;
            }
            break;
        case 1913648695:
            if (var10000.equals("toString()Ljava/lang/String;")) {
                return 2;
            }
            break;
        case 1984935277:
            if (var10000.equals("hashCode()I")) {
                return 3;
            }
        }

        return -1;
    }

    public int getIndex(String var1, Class[] var2) {
        switch(var1.hashCode()) {
        case -1776922004:
            if (var1.equals("toString")) {
                switch(var2.length) {
                case 0:
                    return 2;
                }
            }
            break;
        case -1295482945:
            if (var1.equals("equals")) {
                switch(var2.length) {
                case 1:
                    if (var2[0].getName().equals("java.lang.Object")) {
                        return 1;
                    }
                }
            }
            break;
        case -838846263:
            if (var1.equals("update")) {
                switch(var2.length) {
                case 0:
                    return 0;
                }
            }
            break;
        case 147696667:
            if (var1.equals("hashCode")) {
                switch(var2.length) {
                case 0:
                    return 3;
                }
            }
        }

        return -1;
    }

    public int getIndex(Class[] var1) {
        switch(var1.length) {
        case 0:
            return 0;
        default:
            return -1;
        }
    }

    public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
        UserServiceImpl var10000 = (UserServiceImpl)var2;
        int var10001 = var1;

        try {
            switch(var10001) {
            case 0:
                var10000.update();
                return null;
            case 1:
                return new Boolean(var10000.equals(var3[0]));
            case 2:
                return var10000.toString();
            case 3:
                return new Integer(var10000.hashCode());
            }
        } catch (Throwable var4) {
            throw new InvocationTargetException(var4);
        }

        throw new IllegalArgumentException("Cannot find matching method/constructor");
    }

    public Object newInstance(int var1, Object[] var2) throws InvocationTargetException {
        UserServiceImpl var10000 = new UserServiceImpl;
        UserServiceImpl var10001 = var10000;
        int var10002 = var1;

        try {
            switch(var10002) {
            case 0:
                var10001.<init>();
                return var10000;
            }
        } catch (Throwable var3) {
            throw new InvocationTargetException(var3);
        }

        throw new IllegalArgumentException("Cannot find matching method/constructor");
    }

    public int getMaxIndex() {
        return 3;
    }
}

看看生成的代理类:
以update()方法为例:
在静态代码块中会给代理中的

private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
    private static final Callback[] CGLIB$STATIC_CALLBACKS;
    private MethodInterceptor CGLIB$CALLBACK_0;

属性进行赋值,也就是我们实现的拦截器对象赋值到属性中;
看一下重写的目标方法:

public final void update() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        if (var10000 != null) {
            var10000.intercept(this, CGLIB$update$0$Method, CGLIB$emptyArgs, CGLIB$update$0$Proxy);
        } else {
            super.update();
        }
    }

获取到拦截器对象,执行拦截器中public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy)我们实现的方法,
传参为当前代理对象、目标方法对象、方法参数列表、初始化的MethodProxy对象;

package com.bijian.proxy;

import java.lang.reflect.Method;
import org.springframework.cglib.core.ReflectUtils;
import org.springframework.cglib.core.Signature;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.Factory;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

public class UserServiceImpl$$EnhancerByCGLIB$$dd0048a7 extends UserServiceImpl implements Factory {
    private boolean CGLIB$BOUND;
    public static Object CGLIB$FACTORY_DATA;
    private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
    private static final Callback[] CGLIB$STATIC_CALLBACKS;
    private MethodInterceptor CGLIB$CALLBACK_0;
    private static Object CGLIB$CALLBACK_FILTER;
    private static final Method CGLIB$update$0$Method;
    private static final MethodProxy CGLIB$update$0$Proxy;
    private static final Object[] CGLIB$emptyArgs;
    private static final Method CGLIB$equals$1$Method;
    private static final MethodProxy CGLIB$equals$1$Proxy;
    private static final Method CGLIB$toString$2$Method;
    private static final MethodProxy CGLIB$toString$2$Proxy;
    private static final Method CGLIB$hashCode$3$Method;
    private static final MethodProxy CGLIB$hashCode$3$Proxy;
    private static final Method CGLIB$clone$4$Method;
    private static final MethodProxy CGLIB$clone$4$Proxy;

    static void CGLIB$STATICHOOK1() {
        CGLIB$THREAD_CALLBACKS = new ThreadLocal();
        CGLIB$emptyArgs = new Object[0];
        Class var0 = Class.forName("com.bijian.proxy.UserServiceImpl$$EnhancerByCGLIB$$dd0048a7");
        Class var1;
        CGLIB$update$0$Method = ReflectUtils.findMethods(new String[]{"update", "()V"}, (var1 = Class.forName("com.bijian.proxy.UserServiceImpl")).getDeclaredMethods())[0];
        CGLIB$update$0$Proxy = MethodProxy.create(var1, var0, "()V", "update", "CGLIB$update$0");
        Method[] var10000 = ReflectUtils.findMethods(new String[]{"equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"}, (var1 = Class.forName("java.lang.Object")).getDeclaredMethods());
        CGLIB$equals$1$Method = var10000[0];
        CGLIB$equals$1$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$1");
        CGLIB$toString$2$Method = var10000[1];
        CGLIB$toString$2$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$2");
        CGLIB$hashCode$3$Method = var10000[2];
        CGLIB$hashCode$3$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$3");
        CGLIB$clone$4$Method = var10000[3];
        CGLIB$clone$4$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$4");
    }

    final void CGLIB$update$0() {
        super.update();
    }

    public final void update() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        if (var10000 != null) {
            var10000.intercept(this, CGLIB$update$0$Method, CGLIB$emptyArgs, CGLIB$update$0$Proxy);
        } else {
            super.update();
        }
    }

    final boolean CGLIB$equals$1(Object var1) {
        return super.equals(var1);
    }

    public final boolean equals(Object var1) {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        if (var10000 != null) {
            Object var2 = var10000.intercept(this, CGLIB$equals$1$Method, new Object[]{var1}, CGLIB$equals$1$Proxy);
            return var2 == null ? false : (Boolean)var2;
        } else {
            return super.equals(var1);
        }
    }

    final String CGLIB$toString$2() {
        return super.toString();
    }

    public final String toString() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        return var10000 != null ? (String)var10000.intercept(this, CGLIB$toString$2$Method, CGLIB$emptyArgs, CGLIB$toString$2$Proxy) : super.toString();
    }

    final int CGLIB$hashCode$3() {
        return super.hashCode();
    }

    public final int hashCode() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        if (var10000 != null) {
            Object var1 = var10000.intercept(this, CGLIB$hashCode$3$Method, CGLIB$emptyArgs, CGLIB$hashCode$3$Proxy);
            return var1 == null ? 0 : ((Number)var1).intValue();
        } else {
            return super.hashCode();
        }
    }

    final Object CGLIB$clone$4() throws CloneNotSupportedException {
        return super.clone();
    }

    protected final Object clone() throws CloneNotSupportedException {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        return var10000 != null ? var10000.intercept(this, CGLIB$clone$4$Method, CGLIB$emptyArgs, CGLIB$clone$4$Proxy) : super.clone();
    }

    public static MethodProxy CGLIB$findMethodProxy(Signature var0) {
        String var10000 = var0.toString();
        switch(var10000.hashCode()) {
        case -1949253108:
            if (var10000.equals("update()V")) {
                return CGLIB$update$0$Proxy;
            }
            break;
        case -508378822:
            if (var10000.equals("clone()Ljava/lang/Object;")) {
                return CGLIB$clone$4$Proxy;
            }
            break;
        case 1826985398:
            if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
                return CGLIB$equals$1$Proxy;
            }
            break;
        case 1913648695:
            if (var10000.equals("toString()Ljava/lang/String;")) {
                return CGLIB$toString$2$Proxy;
            }
            break;
        case 1984935277:
            if (var10000.equals("hashCode()I")) {
                return CGLIB$hashCode$3$Proxy;
            }
        }

        return null;
    }

    public UserServiceImpl$$EnhancerByCGLIB$$dd0048a7() {
        CGLIB$BIND_CALLBACKS(this);
    }

    public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) {
        CGLIB$THREAD_CALLBACKS.set(var0);
    }

    public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] var0) {
        CGLIB$STATIC_CALLBACKS = var0;
    }


/**
	 * CGLIB$BIND_CALLBACKS 先从CGLIB$THREAD_CALLBACKS(一个ThreadLocal对象)中getCallback
	 * 如果获取不到的话,再从CGLIB$STATIC_CALLBACKS来获取,如果也没有则认为该方法不需要代理。
     * 那么CallBack是如何设置到CGLIB$THREAD_CALLBACKS 或者 CGLIB$STATIC_CALLBACKS中的呢?
     * 在Jdk动态代理中拦截对象是在实例化代理类时由构造函数传入的
	     * 在cglib中我们使用Enhancers生成代理类时。是调用Enhancer的firstInstance方法来生成代理类实例并设置回调。
     * firstInstance的调用轨迹为:
		   1.Enhancer:firstInstance
		   2.Enhancer:createUsingReflection
		   3.Enhancer:setThreadCallbacks
		   4.Enhancer:setCallbacksHelper
		   5.Target$$EnhancerByCGLIB$$788444a0 : CGLIB$SET_THREAD_CALLBACKS
	 * 最终CGLIB实例化代理对象的时候,就在这里将所有的Callback成功设置了
	 */
    private static final void CGLIB$BIND_CALLBACKS(Object var0) {
        UserServiceImpl$$EnhancerByCGLIB$$dd0048a7 var1 = (UserServiceImpl$$EnhancerByCGLIB$$dd0048a7)var0;
        if (!var1.CGLIB$BOUND) {
            var1.CGLIB$BOUND = true;
            Object var10000 = CGLIB$THREAD_CALLBACKS.get();
            if (var10000 == null) {
                var10000 = CGLIB$STATIC_CALLBACKS;
                if (var10000 == null) {
                    return;
                }
            }

            var1.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])var10000)[0];
        }

    }

    public Object newInstance(Callback[] var1) {
        CGLIB$SET_THREAD_CALLBACKS(var1);
        UserServiceImpl$$EnhancerByCGLIB$$dd0048a7 var10000 = new UserServiceImpl$$EnhancerByCGLIB$$dd0048a7();
        CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
        return var10000;
    }

    public Object newInstance(Callback var1) {
        CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});
        UserServiceImpl$$EnhancerByCGLIB$$dd0048a7 var10000 = new UserServiceImpl$$EnhancerByCGLIB$$dd0048a7();
        CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
        return var10000;
    }

    public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
        CGLIB$SET_THREAD_CALLBACKS(var3);
        UserServiceImpl$$EnhancerByCGLIB$$dd0048a7 var10000 = new UserServiceImpl$$EnhancerByCGLIB$$dd0048a7;
        switch(var1.length) {
        case 0:
            var10000.<init>();
            CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
            return var10000;
        default:
            throw new IllegalArgumentException("Constructor not found");
        }
    }

    public Callback getCallback(int var1) {
        CGLIB$BIND_CALLBACKS(this);
        MethodInterceptor var10000;
        switch(var1) {
        case 0:
            var10000 = this.CGLIB$CALLBACK_0;
            break;
        default:
            var10000 = null;
        }

        return var10000;
    }

    public void setCallback(int var1, Callback var2) {
        switch(var1) {
        case 0:
            this.CGLIB$CALLBACK_0 = (MethodInterceptor)var2;
        default:
        }
    }

    public Callback[] getCallbacks() {
        CGLIB$BIND_CALLBACKS(this);
        return new Callback[]{this.CGLIB$CALLBACK_0};
    }

    public void setCallbacks(Callback[] var1) {
        this.CGLIB$CALLBACK_0 = (MethodInterceptor)var1[0];
    }

    static {
        CGLIB$STATICHOOK1();
    }
}

CGLIB$STATICHOOK1()这个静态方法内执行了MethodProxy.create()方法,为被代理所有的方法都生成了对应的MethodProxy,在调用代理对象的每个方法是都会有一个对应的MethodProxy就会当参数被传递到MethodInterceptor.intercept()方法中,在intercept中就能利用MethodProxy类的方法,使用FastClass机制

MethodProxy中的部分方法:

/**
 * 一个MethodProxy对象,包含了两个方法的名称,一个是被代理类中的原始方法
 * 另外一个则是代理类中生成的用来调用被代理类原始方法的方法名
 * 当执行MethodProxy.invoke()方法时,其实就是用的被代理类的方法索引
 * 当执行MethodProxy.invokeSuper()方法时,用的是代理类中的方法的索引
 * 
 * c1是被代理类的class,也就是com.bijian.proxy.UserServiceImpl
 * c2是代理类的class
 * name1是被代理类中的原始方法名(也就是代理类中的重写的方法名)
 * name2是代理类中新增的用来调用被代理类原始方法的方法的名字

这个类中的属性:sig1 为原始的方法签名   sig2为代理类中中新增的用来调用被代理类原始方法的方法签名
 */
public static MethodProxy create(Class c1, Class c2, String desc, String name1, String name2) {
    MethodProxy proxy = new MethodProxy();
    // Signature是用来标识一个唯一的方法
// 该标识可以用来获取fastClass中每一个方法的索引
    proxy.sig1 = new Signature(name1, desc);
    proxy.sig2 = new Signature(name2, desc);
    proxy.createInfo = new CreateInfo(c1, c2);
    return proxy;
}

private void init()
{
    /* 
     * Using a volatile invariant allows us to initialize the FastClass and
     * method index pairs atomically.
     * 
     * Double-checked locking is safe with volatile in Java 5.  Before 1.5 this 
     * code could allow fastClassInfo to be instantiated more than once, which
     * appears to be benign.
     */
    if (fastClassInfo == null)
    {
        synchronized (initLock)
        {
            if (fastClassInfo == null)
            {
                CreateInfo ci = createInfo;
                FastClassInfo fci = new FastClassInfo();
                // helper中生成了对应Class的FastClass实例,这里可以看出就是生成了两个Class的FastClass
// f1为被代理类的class,也就是com.bijian.proxy.UserServiceImpl的的FastClass对象;f2为代理类的FastClass实例
                fci.f1 = helper(ci, ci.c1);
                fci.f2 = helper(ci, ci.c2);
                // 获取方法的下标,sig1原本的方法名,sig2是为了调用父类方法生成的特殊方法的方法名
// i1为被代理类的目标方法索引下标, i2为代理类中的调用父类方法生成的特殊方法的索引下标
                fci.i1 = fci.f1.getIndex(sig1);
                fci.i2 = fci.f2.getIndex(sig2);
                // 存储在本地变量上
                fastClassInfo = fci;
                createInfo = null;
            }
        }
    }
}

public Object invokeSuper(Object obj, Object[] args) throws Throwable {
    try {
    	// 调用init方法,当前MethodProxy就是代理类中初始化的,创建步骤上面已经说过      
  init();
        FastClassInfo fci = fastClassInfo;
        // 这里的f2就是一个FastClass,fci.i2就是在init方法中计算出来的索引:代理类中的调用父类方法生成的特殊方法的索引下标;所以Object obj必须穿代理类对象;不然会报错;
        return fci.f2.invoke(fci.i2, obj, args);
    } catch (InvocationTargetException e) {
        throw e.getTargetException();
    }
}

public Object invoke(Object obj, Object[] args) throws Throwable {
    try {
        init();
 // 这里的f1就是一个FastClass; fci.i1为被代理类的目标方法索引下标 ,这里的obj穿被代理类对象,否则会报错;栈内存溢出,如果穿的是代理类,则会执行代理类中重写的目标方法,无线循环调用
        FastClassInfo fci = fastClassInfo;
        return fci.f1.invoke(fci.i1, obj, args);
    } catch (InvocationTargetException e) {
        throw e.getTargetException();
    } catch (IllegalArgumentException e) {
        if (fastClassInfo.i1 < 0)
            throw new IllegalArgumentException("Protected method: " + sig1);
        throw e;
    }
}

private static class FastClassInfo
{
	// 被代理类的FastClass
    FastClass f1;
    // 代理类的FastClass
    FastClass f2;
    int i1;
    int i2;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值