• 动态代理记录


    Cglib代理

    定义目标类

    public class Person {
        public void sayHello() {
            System.out.println("Hello!");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    Cglib代理后的类的Class

      

    System.setProperty(
    DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "E://xiaobaidemo");
    
    • 1
    • 2

    这行代码用来生成cglib生成的代理类,输出到指定目录

    System.setProperty(
    DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "E://xiaobaidemo")
    
    • 1
    • 2
    代理逻辑
    public class Test20221111 {
        public static void main(String[] args) {
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "E://xiaobaidemo");
            Enhancer.create(Person.class, new MethodInterceptor() {
                @Override
                public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                    System.out.println("Intercept!");
                    methodProxy.invokeSuper(o, objects);
                    return null;
                }
            });
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    反编译后的Class

    https://juejin.cn/post/6844904077877313549

    public class Person$$EnhancerByCGLIB$$34b905e4
    extends Person {
        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$sayHello$0$Method;
        private static final MethodProxy CGLIB$sayHello$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$STATICHOOK2() {
            CGLIB$THREAD_CALLBACKS = new ThreadLocal();
            CGLIB$emptyArgs = new Object[0];
            Class class_ = Class.forName("Person$$EnhancerByCGLIB$$34b905e4");
            Class class_2 = Class.forName("java.lang.Object");
            Method[] arrmethod = ReflectUtils.findMethods((String[])new String[]{"equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"}, (Method[])class_2.getDeclaredMethods());
            CGLIB$equals$1$Method = arrmethod[0];
            CGLIB$equals$1$Proxy = MethodProxy.create(class_2, class_, (String)"(Ljava/lang/Object;)Z", (String)"equals", (String)"CGLIB$equals$1");
            CGLIB$toString$2$Method = arrmethod[1];
            CGLIB$toString$2$Proxy = MethodProxy.create(class_2, class_, (String)"()Ljava/lang/String;", (String)"toString", (String)"CGLIB$toString$2");
            CGLIB$hashCode$3$Method = arrmethod[2];
            CGLIB$hashCode$3$Proxy = MethodProxy.create(class_2, class_, (String)"()I", (String)"hashCode", (String)"CGLIB$hashCode$3");
            CGLIB$clone$4$Method = arrmethod[3];
            CGLIB$clone$4$Proxy = MethodProxy.create(class_2, class_, (String)"()Ljava/lang/Object;", (String)"clone", (String)"CGLIB$clone$4");
            class_2 = Class.forName("Person");
            CGLIB$sayHello$0$Method = ReflectUtils.findMethods((String[])new String[]{"sayHello", "()V"}, (Method[])class_2.getDeclaredMethods())[0];
            CGLIB$sayHello$0$Proxy = MethodProxy.create(class_2, class_, (String)"()V", (String)"sayHello", (String)"CGLIB$sayHello$0");
        }
    
        final void CGLIB$sayHello$0() {
            super.sayHello();
        }
    
        public final void sayHello() {
            MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;
            if (methodInterceptor == null) {
                Person$$EnhancerByCGLIB$$34b905e4.CGLIB$BIND_CALLBACKS((Object)this);
                methodInterceptor = this.CGLIB$CALLBACK_0;
            }
            if (methodInterceptor != null) {
                Object object = methodInterceptor.intercept((Object)this, CGLIB$sayHello$0$Method, CGLIB$emptyArgs, CGLIB$sayHello$0$Proxy);
                return;
            }
            super.sayHello();
        }
    
        final boolean CGLIB$equals$1(Object object) {
            return super.equals(object);
        }
    
        public final boolean equals(Object object) {
            MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;
            if (methodInterceptor == null) {
                Person$$EnhancerByCGLIB$$34b905e4.CGLIB$BIND_CALLBACKS((Object)this);
                methodInterceptor = this.CGLIB$CALLBACK_0;
            }
            if (methodInterceptor == null) return super.equals(object);
            Object object2 = methodInterceptor.intercept((Object)this, CGLIB$equals$1$Method, new Object[]{object}, CGLIB$equals$1$Proxy);
            if (object2 == null) {
                return false;
            }
            boolean bl = (Boolean)object2;
            return bl;
        }
    
        final String CGLIB$toString$2() {
            return super.toString();
        }
    
        public final String toString() {
            MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;
            if (methodInterceptor == null) {
                Person$$EnhancerByCGLIB$$34b905e4.CGLIB$BIND_CALLBACKS((Object)this);
                methodInterceptor = this.CGLIB$CALLBACK_0;
            }
            if (methodInterceptor == null) return super.toString();
            return (String)methodInterceptor.intercept((Object)this, CGLIB$toString$2$Method, CGLIB$emptyArgs, CGLIB$toString$2$Proxy);
        }
    
        final int CGLIB$hashCode$3() {
            return super.hashCode();
        }
    
        public final int hashCode() {
            MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;
            if (methodInterceptor == null) {
                Person$$EnhancerByCGLIB$$34b905e4.CGLIB$BIND_CALLBACKS((Object)this);
                methodInterceptor = this.CGLIB$CALLBACK_0;
            }
            if (methodInterceptor == null) return super.hashCode();
            Object object = methodInterceptor.intercept((Object)this, CGLIB$hashCode$3$Method, CGLIB$emptyArgs, CGLIB$hashCode$3$Proxy);
            if (object == null) {
                return 0;
            }
            int n = ((Number)object).intValue();
            return n;
        }
    
        final Object CGLIB$clone$4() throws CloneNotSupportedException {
            return super.clone();
        }
    
        protected final Object clone() throws CloneNotSupportedException {
            MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;
            if (methodInterceptor == null) {
                Person$$EnhancerByCGLIB$$34b905e4.CGLIB$BIND_CALLBACKS((Object)this);
                methodInterceptor = this.CGLIB$CALLBACK_0;
            }
            if (methodInterceptor == null) return super.clone();
            return methodInterceptor.intercept((Object)this, CGLIB$clone$4$Method, CGLIB$emptyArgs, CGLIB$clone$4$Proxy);
        }
    
        public static MethodProxy CGLIB$findMethodProxy(Signature signature) {
            String string = signature.toString();
            switch (string.hashCode()) {
                case -508378822: {
                    if (!string.equals("clone()Ljava/lang/Object;")) return null;
                    return CGLIB$clone$4$Proxy;
                }
                case 1535311470: {
                    if (!string.equals("sayHello()V")) return null;
                    return CGLIB$sayHello$0$Proxy;
                }
                case 1826985398: {
                    if (!string.equals("equals(Ljava/lang/Object;)Z")) return null;
                    return CGLIB$equals$1$Proxy;
                }
                case 1913648695: {
                    if (!string.equals("toString()Ljava/lang/String;")) return null;
                    return CGLIB$toString$2$Proxy;
                }
                case 1984935277: {
                    if (!string.equals("hashCode()I")) return null;
                    return CGLIB$hashCode$3$Proxy;
                }
            }
            return null;
        }
    
        public Person$$EnhancerByCGLIB$$34b905e4() {
            Person$$EnhancerByCGLIB$$34b905e4 person$$EnhancerByCGLIB$$34b905e4 = this;
            Person$$EnhancerByCGLIB$$34b905e4.CGLIB$BIND_CALLBACKS((Object)person$$EnhancerByCGLIB$$34b905e4);
        }
    
        public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] arrcallback) {
            CGLIB$THREAD_CALLBACKS.set(arrcallback);
        }
    
        public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] arrcallback) {
            CGLIB$STATIC_CALLBACKS = arrcallback;
        }
    
        private static final void CGLIB$BIND_CALLBACKS(Object object) {
            Person$$EnhancerByCGLIB$$34b905e4 person$$EnhancerByCGLIB$$34b905e4 = (Person$$EnhancerByCGLIB$$34b905e4)object;
            if (person$$EnhancerByCGLIB$$34b905e4.CGLIB$BOUND) return;
            person$$EnhancerByCGLIB$$34b905e4.CGLIB$BOUND = true;
            Object t = CGLIB$THREAD_CALLBACKS.get();
            if (t == null && (v783 = CGLIB$STATIC_CALLBACKS) == null) {
                return;
            }
            person$$EnhancerByCGLIB$$34b905e4.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])t)[0];
        }
    
        static {
            Person$$EnhancerByCGLIB$$34b905e4.CGLIB$STATICHOOK2();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177

      在创建一个代理类的对象的时候,会先加载这个Cglib创建的代理类的静态方法CGLIB$STATICHOOK2()。这个函数中对类的其他静态字段进行了初始化。例如:对那个每个需要代理的方法都生成两个字段,一个用于反射的Method对象,另一个用于加快方法调用,避免反射带来的开销的MethodProxy对象。然后在构造函数里面调用了GCLIB$BIND_CALLBACKS(this),在CGLIB$BIND_CALLBACKS方法中会把private MethodInterceptor CGLIB$CALLBACK_0字段和设置的静态变量ThreadLocal CGLIB$THREAD_CALLBACKS进行绑定,也就是说,设置的Callback并不是硬编码在生成代理类里面的,而是可以动态的设置。
      由于代理类继承了被代理类,所以调用sayHello()方法时会直接调用代理类的sayHello()方法,而在代理类的方法中,调用了Callback的逻辑。
      MethodInterceptor的interceptor方法参数:

     if (methodInterceptor != null) {
                Object object = methodInterceptor.intercept((Object)this, CGLIB$sayHello$0$Method, CGLIB$emptyArgs, CGLIB$sayHello$0$Proxy);
                return;
            }
    
    • 1
    • 2
    • 3
    • 4

      ①代理对象
      ②目标类的方法 CGLIB$sayHello$0$Method。通过目标类反射获取的方法
      ③方法参数
      ④目标类的代理方法CGLIB$sayHello$0$Proxy

    MethodProxy.create

      MethodProxy是cglib包中提供的一个类。

    package org.springframework.cglib.proxy;
    
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    import org.springframework.cglib.core.AbstractClassGenerator;
    import org.springframework.cglib.core.CodeGenerationException;
    import org.springframework.cglib.core.GeneratorStrategy;
    import org.springframework.cglib.core.NamingPolicy;
    import org.springframework.cglib.core.Signature;
    import org.springframework.cglib.reflect.FastClass;
    
    /**
     * Classes generated by {@link Enhancer} pass this object to the
     * registered {@link MethodInterceptor} objects when an intercepted method is invoked. It can
     * be used to either invoke the original method, or call the same method on a different
     * object of the same type.
     * @version $Id: MethodProxy.java,v 1.16 2009/01/11 20:09:48 herbyderby Exp $
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    public class MethodProxy {
    
    	private Signature sig1;
    
    	private Signature sig2;
    
    	private CreateInfo createInfo;
    
    	private final Object initLock = new Object();
    
    	private volatile FastClassInfo fastClassInfo;
    
    	/**
    	 * For internal use by {@link Enhancer} only; see the {@link org.springframework.cglib.reflect.FastMethod} class
    	 * for similar functionality.
    	 *  看这里。看这里。看这里。create方法构建一个MethodProxy对象。
    	 *  ① Class c1 是目标对象的Class
    	 *  ② Class c2 是代理对象的Class
    	 *  ③ desc 是否方法描述
    	 *  ④ name1 是目标对象的方法名
    	 *  ⑤ name2 是代理对象的方法名
    	 */
    	public static MethodProxy create(Class c1, Class c2, String desc, String name1, String name2) {
    		MethodProxy proxy = new MethodProxy();
    		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();
    					fci.f1 = helper(ci, ci.c1);
    					fci.f2 = helper(ci, ci.c2);
    					fci.i1 = fci.f1.getIndex(sig1);
    					fci.i2 = fci.f2.getIndex(sig2);
    					fastClassInfo = fci;
    					createInfo = null;
    				}
    			}
    		}
    	}
    
    
    	private static class FastClassInfo {
    
    		FastClass f1;
    
    		FastClass f2;
    
    		int i1;
    
    		int i2;
    	}
    
    
    	private static class CreateInfo {
    
    		Class c1;
    
    		Class c2;
    
    		NamingPolicy namingPolicy;
    
    		GeneratorStrategy strategy;
    
    		boolean attemptLoad;
    
    		public CreateInfo(Class c1, Class c2) {
    			this.c1 = c1;
    			this.c2 = c2;
    			AbstractClassGenerator fromEnhancer = AbstractClassGenerator.getCurrent();
    			if (fromEnhancer != null) {
    				namingPolicy = fromEnhancer.getNamingPolicy();
    				strategy = fromEnhancer.getStrategy();
    				attemptLoad = fromEnhancer.getAttemptLoad();
    			}
    		}
    	}
    
    
    	private static FastClass helper(CreateInfo ci, Class type) {
    		FastClass.Generator g = new FastClass.Generator();
    		g.setType(type);
    		// SPRING PATCH BEGIN
    		g.setContextClass(type);
    		// SPRING PATCH END
    		g.setClassLoader(ci.c2.getClassLoader());
    		g.setNamingPolicy(ci.namingPolicy);
    		g.setStrategy(ci.strategy);
    		g.setAttemptLoad(ci.attemptLoad);
    		return g.create();
    	}
    
    	private MethodProxy() {
    	}
    
    	/**
    	 * Return the signature of the proxied method.
    	 */
    	public Signature getSignature() {
    		return sig1;
    	}
    
    	/**
    	 * Return the name of the synthetic method created by CGLIB which is
    	 * used by {@link #invokeSuper} to invoke the superclass
    	 * (non-intercepted) method implementation. The parameter types are
    	 * the same as the proxied method.
    	 */
    	public String getSuperName() {
    		return sig2.getName();
    	}
    
    	/**
    	 * Return the {@link org.springframework.cglib.reflect.FastClass} method index
    	 * for the method used by {@link #invokeSuper}. This index uniquely
    	 * identifies the method within the generated proxy, and therefore
    	 * can be useful to reference external metadata.
    	 * @see #getSuperName
    	 */
    	public int getSuperIndex() {
    		init();
    		return fastClassInfo.i2;
    	}
    
    	// For testing
    	FastClass getFastClass() {
    		init();
    		return fastClassInfo.f1;
    	}
    
    	// For testing
    	FastClass getSuperFastClass() {
    		init();
    		return fastClassInfo.f2;
    	}
    
    	/**
    	 * Return the MethodProxy used when intercepting the method
    	 * matching the given signature.
    	 * @param type the class generated by Enhancer
    	 * @param sig the signature to match
    	 * @return the MethodProxy instance, or null if no applicable matching method is found
    	 * @throws IllegalArgumentException if the Class was not created by Enhancer or does not use a MethodInterceptor
    	 */
    	public static MethodProxy find(Class type, Signature sig) {
    		try {
    			Method m = type.getDeclaredMethod(MethodInterceptorGenerator.FIND_PROXY_NAME,
    					MethodInterceptorGenerator.FIND_PROXY_TYPES);
    			return (MethodProxy) m.invoke(null, new Object[]{sig});
    		}
    		catch (NoSuchMethodException ex) {
    			throw new IllegalArgumentException("Class " + type + " does not use a MethodInterceptor");
    		}
    		catch (IllegalAccessException | InvocationTargetException ex) {
    			throw new CodeGenerationException(ex);
    		}
    	}
    
    	/**
    	 * Invoke the original method, on a different object of the same type.
    	 * @param obj the compatible object; recursion will result if you use the object passed as the first
    	 * argument to the MethodInterceptor (usually not what you want)
    	 * @param args the arguments passed to the intercepted method; you may substitute a different
    	 * argument array as long as the types are compatible
    	 * @throws Throwable the bare exceptions thrown by the called method are passed through
    	 * without wrapping in an InvocationTargetException
    	 * @see MethodInterceptor#intercept
    	 */
    	public Object invoke(Object obj, Object[] args) throws Throwable {
    		try {
    			init();
    			FastClassInfo fci = fastClassInfo;
    			return fci.f1.invoke(fci.i1, obj, args);
    		}
    		catch (InvocationTargetException ex) {
    			throw ex.getTargetException();
    		}
    		catch (IllegalArgumentException ex) {
    			if (fastClassInfo.i1 < 0)
    				throw new IllegalArgumentException("Protected method: " + sig1);
    			throw ex;
    		}
    	}
    
    	/**
    	 * Invoke the original (super) method on the specified object.
    	 * @param obj the enhanced object, must be the object passed as the first
    	 * argument to the MethodInterceptor
    	 * @param args the arguments passed to the intercepted method; you may substitute a different
    	 * argument array as long as the types are compatible
    	 * @throws Throwable the bare exceptions thrown by the called method are passed through
    	 * without wrapping in an InvocationTargetException
    	 * @see MethodInterceptor#intercept
    	 *  看这里,看这里,看这里
    	 *  当调用methodProxy的invokeSuper方法的时候。传入的是代理对象obj,方法参数args。
    	 *  ①首先调用init方法。
    	 *  ②构建FastClassInfo对象,FastClassInfo对象的成员变量赋值。f1是目标对象的FastClass对象,f2是代理对象的FastClass对象。注意:FastClassInfo和FastClass对象是不一样的。
    	 *  ③ FastClassInfo对象设置属性i1 = 目标对象方法的索引。i2 = 代理对象方法的索引
    	 *  ④ 设置methodProxy的变量fastClassInfo = 创建的fastClassInfo对象
    	 *  ⑤ 调用f2对象的fastClass对象的invoke方法。传入方法的坐标,代理对象,方法参数。
    	 *  (1) fci.f2 = 代理对象的fastClass对象。调用代理对象的fastClass的invoke方法。
    	 *  (2) invoke方法参数中fci.i2表示的是代理对象方法的索引。比如上文中sayHello(目标对象的方法),CGLIB$sayHello$0(代理对象的方法)。这里执行的是代理对象的方法。obj是代理对象,args是方法参数。
    	 *  (3)根据索引找到匹配的方法,直接执行obj对象的方法。
    	 */
    	public Object invokeSuper(Object obj, Object[] args) throws Throwable {
    		try {
    			init();
    			FastClassInfo fci = fastClassInfo;
    			return fci.f2.invoke(fci.i2, obj, args);
    		}
    		catch (InvocationTargetException e) {
    			throw e.getTargetException();
    		}
    	}
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251

      java反射调用方法是比较“重”的操作,要经过一系列的权限验证、通过native方法请求jvm去方法区查找方法定义、以及最后的invoke仍然可能要通过JNI调用native方法。而相比之下,FastClass方式则跟一般的一个普通的对象方法调用没啥区别、只是多了一步根据index判断调用委托类的哪个方法这一步骤、性能损耗基本没有。
      cglib的大概逻辑如下:
      (1)ASM构建代理类。继承目标类。代理类实例化过程:
      ①调用静态代码块,调用静态方法,对类中静态属性赋值。关键点是。对目标类中的所有方法,生成两个变量,一个Method,表示目标类方法。一个MethodProxy,表示通过MethodProxy构建的methodProxy。
      ②MethodProxy里面的fastClassInfo属性,保存了代理类fastClass,目标类fastClass,代理类方法索引,目标类方法索引。
      ③方法拦截中执行MethodProxy的invokeSupper方法,里面通过fastClassInfo获取代理类的fastClass类,然后调用fastClass的invoke方法。
      ④fastclass的invoke方法根据传入的方法索引,直接对象的方法。
    fastClass机制
    在这里插入图片描述
      综上可以看出,FastClass调用invoke,其实就是将Object转换为目标类或者代理类。根据索引,直接调用对象的相关方法。

    拦截器中调用MethodProxy.invoke()方法会死循环,为什么?原因如下:

      (1)MethodProxy.invoke。调用的是目标对象的方法,多态特性,调用的还是代理类中的sayHello方法,接着还会去调用拦截方法,拦截方法中调用MethodProxy.invoke,接着调用代理类的sayHello方法…陷入死循环。

      public final void sayHello() {
            MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;
            if (methodInterceptor == null) {
                Person$$EnhancerByCGLIB$$34b905e4.CGLIB$BIND_CALLBACKS((Object)this);
                methodInterceptor = this.CGLIB$CALLBACK_0;
            }
            if (methodInterceptor != null) {
               // 被代理方法(methodProxy.invoke会调用)
                Object object = methodInterceptor.intercept((Object)this, CGLIB$sayHello$0$Method, CGLIB$emptyArgs, CGLIB$sayHello$0$Proxy);
                return;
            }
            super.sayHello();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

      (2)MethodProxy.invokeSuper。调用的是代理对象中的代理方法(CGLIB$sayHello$0),调用的是目标类中的sayHello方法。

     final void CGLIB$sayHello$0() {
            super.sayHello();
        }
    
    • 1
    • 2
    • 3
    Method.invoke 和 MethodProxy.invokeSuper

      先了解一个概念:FastClass机制。Cglib动态代理方法效率之所以比Jdk的高。就是因为Cglib采用了FastClass机制。
      FastClass机制:为代理类和目标类各生成一个Class,这个Class会为代理类或目标类的方法分配一个index(int类型)。这个index当做一个入参,FastClass就可以直接定位要调用的方法直接进行调用,这样省去了反射调用,所以调用效率比jdk动态代理通过反射调用高。
      FastClass反编译:

     //根据方法签名获取index
     public int getIndex(Signature var1) {
          String var10000 = var1.toString();
          switch(var10000.hashCode()) {
          case -2077043409:
             if(var10000.equals("getPerson(Ljava/lang/String;)Lcom/demo/pojo/Person;")) {
                return 21;
             }
             break;
          case -2055565910:
             if(var10000.equals("CGLIB$SET_THREAD_CALLBACKS([Lnet/sf/cglib/proxy/Callback;)V")) {
                return 12;
             }
             break;
          case -1902447170:
             if(var10000.equals("setPerson()V")) {
                return 7;
             }
             break;
       //省略部分代码.....
     
     //根据index直接定位执行方法
     public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
          eaaaed75 var10000 = (eaaaed75)var2;
          int var10001 = var1;
    
          try {
             switch(var10001) {
             case 0:
                return new Boolean(var10000.equals(var3[0]));
             case 1:
                return var10000.toString();
             case 2:
                return new Integer(var10000.hashCode());
             case 3:
                return var10000.newInstance((Class[])var3[0], (Object[])var3[1], (Callback[])var3[2]);
             case 4:
                return var10000.newInstance((Callback)var3[0]);
             case 5:
                return var10000.newInstance((Callback[])var3[0]);
             case 6:
                var10000.setCallback(((Number)var3[0]).intValue(), (Callback)var3[1]);
                return null;
             case 7:
                var10000.setPerson();
                return null;
             case 8:
                var10000.setCallbacks((Callback[])var3[0]);
                return null;
             case 9:
                return var10000.getCallback(((Number)var3[0]).intValue());
             case 10:
                return var10000.getCallbacks();
             case 11:
                eaaaed75.CGLIB$SET_STATIC_CALLBACKS((Callback[])var3[0]);
                return null;
             case 12:
                eaaaed75.CGLIB$SET_THREAD_CALLBACKS((Callback[])var3[0]);
                return null;
             case 13:
                return eaaaed75.CGLIB$findMethodProxy((Signature)var3[0]);
             case 14:
                return var10000.CGLIB$toString$3();
             case 15:
                return new Boolean(var10000.CGLIB$equals$2(var3[0]));
             case 16:
                return var10000.CGLIB$clone$5();
             case 17:
                return new Integer(var10000.CGLIB$hashCode$4());
             case 18:
                var10000.CGLIB$finalize$1();
                return null;
             case 19:
                var10000.CGLIB$setPerson$0();
                return null;
            //省略部分代码....
          } catch (Throwable var4) {
             throw new InvocationTargetException(var4);
          }
    
          throw new IllegalArgumentException("Cannot find matching method/constructor");
       }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82

      FastClass并不是跟代理类一块生成的,而是在第一次执行MethodProxy的invoke/invokeSuper时生成并放在缓存中。

    private void init() {
            if(this.fastClassInfo == null) {
                Object var1 = this.initLock;
                synchronized(this.initLock) {
                    if(this.fastClassInfo == null) {
                        MethodProxy.CreateInfo ci = this.createInfo;
                        MethodProxy.FastClassInfo fci = new MethodProxy.FastClassInfo();
                        fci.f1 = helper(ci, ci.c1);//如果缓存中就取出,没有就生成新的FastClass
                        fci.f2 = helper(ci, ci.c2);
                        fci.i1 = fci.f1.getIndex(this.sig1);//获取方法的index
                        fci.i2 = fci.f2.getIndex(this.sig2);
                        this.fastClassInfo = fci;
                        this.createInfo = null;
                    }
                }
            }
    
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    JDK动态代理

    定义目标类

    public interface HelloService {
       void sayHello();
    }
    
    • 1
    • 2
    • 3
    public class HelloServiceImpl implements HelloService {
       @Override
       public void sayHello(){
           System.out.println(”hello Word“);
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    public class HelloServiceImplHandle implements InvocationHandler{
       private Object target;
    
      public HelloServiceImplHandle(Object target) {
         this.target = target;
      }
      
       @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("proxy before=======");
            Object result = method.invoke(target, args);
            System.out.println("proxy end=======");
            return result;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    生成代理

    HelloService  helloService = new HelloServiceImplHandle();
    HelloServiceImplHandle  helloServiceImplHandle  = new HelloServiceImplHandle();
    Proxy.newProxyInstance(helloService .getClass().getClassLoad(),helloService .getClass().getInterfaces(),helloServiceImplHandle  )
    
    • 1
    • 2
    • 3

    代理类反编译

    public final class $Proxy0 extends Proxy implements HelloService {
        private static Method m1; //equals()方法
        private static Method m3; //我们的sayHello方法()
        private static Method m2; //toString()方法
        private static Method m0; //hashCode()方法
        
        //这里就是我们之前提交的InvocationHandler这个构造方法!!
        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})).booleanValue();
            } catch (RuntimeException | Error var3) {
                throw var3;
            } catch (Throwable var4) {
                throw new UndeclaredThrowableException(var4);
            }
        }
    
        //看一看我们的代理类的sayHello()方法长什么样子呀!!
        public final void sayHello() throws  {
            try {
                super.h.invoke(this, m3, (Object[])null);
            } 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);
            }
        }
    
        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);
            }
        }
    
        static {
            try {
                m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")});
                m3 = Class.forName("proxy.service.HelloService").getMethod("sayHello", new Class[0]);
                m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
                m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
            } catch (NoSuchMethodException var2) {
                throw new NoSuchMethodError(var2.getMessage());
            } catch (ClassNotFoundException var3) {
                throw new NoClassDefFoundError(var3.getMessage());
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65

      代理类继承Proxy类,Proxy类里面保存了我们定义的InvocationHandler的实现。

    public class Proxy implements java.io.Serializable {
        private static final long serialVersionUID = -2222568056686623797L;
        // 这个就是我们定义的InvocationHandler 的实现
        protected InvocationHandler h;
    
        private Proxy() {
        }
        
        protected Proxy(InvocationHandler h) {
            Objects.requireNonNull(h);
            this.h = h;
        }
        
        // 我们构建代理对象的方法。这里面将InvocationHandler 进行赋值。
        @CallerSensitive
        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() {
                        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);
            }
        }
        
        @CallerSensitive
        public static InvocationHandler getInvocationHandler(Object proxy)
            throws IllegalArgumentException
        {
            /*
             * Verify that the object is actually a proxy instance.
             */
            if (!isProxyClass(proxy.getClass())) {
                throw new IllegalArgumentException("not a proxy instance");
            }
    
            final Proxy p = (Proxy) proxy;
            final InvocationHandler ih = p.h;
            if (System.getSecurityManager() != null) {
                Class ihClass = ih.getClass();
                Class caller = Reflection.getCallerClass();
                if (ReflectUtil.needsPackageAccessCheck(caller.getClassLoader(),
                                                        ihClass.getClassLoader()))
                {
                    ReflectUtil.checkPackageAccess(ihClass);
                }
            }
    
            return ih;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94

      代理类实例化,首先调用静态代码块。通过反射,获取Object,目标类的Method。赋值给代理类的静态属性。
      代理对象方法的调用。如下。逻辑很清晰,调用:Proxyh(InvocationHandler的实现类)的invoke方法。
      invoke参数:①代理类 ②代理类的静态属性(目标对象的方法Method,本例中是sayHello的Method) ③方法参数

     public final void sayHello() throws  {
            try {
                super.h.invoke(this, m3, (Object[])null);
            } catch (RuntimeException | Error var2) {
                throw var2;
            } catch (Throwable var3) {
                throw new UndeclaredThrowableException(var3);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
  • 相关阅读:
    K. Kingdom‘s Power,树形dp
    【算法练习Day26】分发饼干&&摆动序列&& 最大子数组和
    Java集合之Map
    SSL证书申请安全审核失败?
    华为云认证的售前工程师是什么?
    2023高教社杯 国赛数学建模E题思路 - 黄河水沙监测数据分析
    跨境电商自养号测评干货分享:从环境搭建到安全养号
    企业微信H5开发遇到的坑
    HTML做一个简单漂亮的宠物网页(纯html代码)
    1. Pytorch的基本语法
  • 原文地址:https://blog.csdn.net/xiaopang2020/article/details/127802957