• Spring温故而知新 – 动态代理


    AOP的概念

    AOP:Aspect-Oriented Programming(面向切面编程),维基百科的解释如下:Aspect是一种新的模块化机制,用来描述分散在对象、类或者函数中的横切关注点,从关注点中分离出横切关注点是面向切面的程序设计的核心概念。分离关注点使解决特定领域问题的代码从业务逻辑中独立出来,业务逻辑的代码中不在含有针对特定领域问题的代码的调用,业务逻辑同特定领域问题的关系通过切面来封装、维护,这样原本分散在整个应用程序中的变动就可以很好地管理起来。从AOP的角度,应用可以分为横切关注点和业务逻辑代码,实际开发中,这些横切关注点往往会直接嵌入到业务逻辑代码中,面向切面编程就是要解决把横切关注点与业务逻辑相分离

    实现方式:

    Spring默认使用 JDK 动态代理作为AOP的代理,缺陷是目标类的类必须实现接口,否则不能使用JDK动态代理。如果需要代理的是类而不是接口,那么Spring会默认使用CGLIB代理,关于两者的区别:jdk动态代理是通过java的反射机制来实现的,目标类必须要实现接口,cglib是针对类来实现代理的,他的原理是动态的为指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。

    JDK动态代理

    Jdk动态代理是在程序运行过程中,根据目标类实现的接口来动态生成代理类的class文件,使用主要涉及两个类:

    InvocationHandler接口: 它提供了一个invoke(Object obj,Method method, Object[] args)方法供实现者提供相应的代理逻辑的实现。可以对实际的实现进行一些特殊的处理其中参数

                Object obj :被代理的目标类

                Method method: 需要执行的目标类的方法

                Object[] args :目标方法的参数

    Proxy类:提供一个方法newProxyInstance (ClassLoader loader, Class[] interfaces, InvocationHandler h)来获得动态代理类

    示例代码:

    public interface OrderService {
    
        public void createOrder(); 
    }
    public class OrderServiceImpl implements OrderService {
        
        @Override
        public void createOrder() {
            System.out.println("creating order");
        }
    }
    public class OrderLogger {
        
        public void beforeCreateOrder(){
            System.out.println("before create order");
        }
    
        public void afterCreateOrder(){
            System.out.println("after create order");
        }
    }
    package com.sl.aop;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class ServiceProxy implements InvocationHandler {
        private Object targetClass;
        private OrderLogger orderLogger;
    
        public ServiceProxy(Object targetClass,OrderLogger orderLogger) {
            this.targetClass = targetClass;
            this.orderLogger = orderLogger;
        }
        
        //获取代理
        public Object GetDynamicProxy()
        {
            return Proxy.newProxyInstance(targetClass.getClass().getClassLoader(), //通过这个ClassLoader生成代理对象
                    targetClass.getClass().getInterfaces(),//代理类已实现的接口
                    this);  //动态代理调用方法是关联的InvocationHandler,最终通过此InvocationHandler的invoke方法执行真正的方法
        }
        
        //实现相应的代理逻辑
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            this.orderLogger.beforeCreateOrder();
            Object result= method.invoke(targetClass, args);
            this.orderLogger.afterCreateOrder();
            
            return result;
        }
    
    }

    测试类:

    package com.sl.aop;
    import org.junit.Test;
    public class AopTest {
        @Test
        public void Testdynamicproxy() {
    
            OrderServiceImpl serviceImpl = new OrderServiceImpl();
            OrderLogger logger = new OrderLogger();
            OrderService service = (OrderService) new ServiceProxy(serviceImpl, logger).GetDynamicProxy();
            service.createOrder();
        }
    }

    运行结果:

    到这个其实还是有点困惑,Proxy.newProxyInstance()这个返回的是什么? Invoke方法在哪里调用的?我们看一下JDK源码:看看DK动态代理的过程是什么样的:

    根据源码内部的函数调用Proxy.newProxyInstance()->Proxy.getProxyClass0()->WeakCache.get() ,先定位到

    WeakCache.class:

    public V get(K key, P parameter) {
            Objects.requireNonNull(parameter);
    
            expungeStaleEntries();
    
            Object cacheKey = CacheKey.valueOf(key, refQueue);
    
            // lazily install the 2nd level valuesMap for the particular cacheKey
            ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
            if (valuesMap == null) {
                ConcurrentMap<Object, Supplier<V>> oldValuesMap
                    = map.putIfAbsent(cacheKey,
                                      valuesMap = new ConcurrentHashMap<>());
                if (oldValuesMap != null) {
                    valuesMap = oldValuesMap;
                }
            }
    
            // create subKey and retrieve the possible Supplier<V> stored by that
            // subKey from valuesMap
            Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
            Supplier<V> supplier = valuesMap.get(subKey);
            Factory factory = null;
    
            while (true) {
                if (supplier != null) {
                    // supplier might be a Factory or a CacheValue<V> instance
                    V value = supplier.get();
                    if (value != null) {
                        return value;
                    }
                }
                // else no supplier in cache
                // or a supplier that returned null (could be a cleared CacheValue
                // or a Factory that wasn't successful in installing the CacheValue)
    
                // lazily construct a Factory
                if (factory == null) {
                    factory = new Factory(key, parameter, subKey, valuesMap);
                }
    
                if (supplier == null) {
                    supplier = valuesMap.putIfAbsent(subKey, factory);
                    if (supplier == null) {
                        // successfully installed Factory
                        supplier = factory;
                    }
                    // else retry with winning supplier
                } else {
                    if (valuesMap.replace(subKey, supplier, factory)) {
                        // successfully replaced
                        // cleared CacheEntry / unsuccessful Factory
                        // with our Factory
                        supplier = factory;
                    } else {
                        // retry with current supplier
                        supplier = valuesMap.get(subKey);
                    }
                }
            }
        }

    可以看到函数return value;  而 V value = supplier.get();   继续往下读可以发现 supper=factory,实际上是一个Factory对象,那么继续查看Factory.get()方法

    public synchronized V get() { // serialize access
                // re-check
                Supplier<V> supplier = valuesMap.get(subKey);
                if (supplier != this) {
                    // something changed while we were waiting:
                    // might be that we were replaced by a CacheValue
                    // or were removed because of failure ->
                    // return null to signal WeakCache.get() to retry
                    // the loop
                    return null;
                }
                // else still us (supplier == this)
    
                // create new value
                V value = null;
                try {
                    value = Objects.requireNonNull(valueFactory.apply(key, parameter));
                } finally {
                    if (value == null) { // remove us on failure
                        valuesMap.remove(subKey, this);
                    }
                }
                // the only path to reach here is with non-null value
                assert value != null;
    
                // wrap value with CacheValue (WeakReference)
                CacheValue<V> cacheValue = new CacheValue<>(value);
    
                // try replacing us with CacheValue (this should always succeed)
                if (valuesMap.replace(subKey, this, cacheValue)) {
                    // put also in reverseMap
                    reverseMap.put(cacheValue, Boolean.TRUE);
                } else {
                    throw new AssertionError("Should not reach here");
                }
    
                // successfully replaced us with new CacheValue -> return the value
                // wrapped by it
                return value;
            }

    Return value;那么直接查看赋值语句:value = Objects.requireNonNull(valueFactory.apply(key, parameter)); valueFactory又什么鬼?

    public WeakCache(BiFunction<K, P, ?> subKeyFactory,
                         BiFunction<K, P, V> valueFactory) {
            this.subKeyFactory = Objects.requireNonNull(subKeyFactory);
            this.valueFactory = Objects.requireNonNull(valueFactory);
        }
    
    private static final WeakCache<ClassLoader, Class<?>[], Class<?>>  proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());

    可以知道valueFactory是ProxyClassFactory类型对象,直接查看ProxyClassFactory. Apply()方法

    public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
    
                Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
                for (Class<?> intf : interfaces) {
                    /*
                     * Verify that the class loader resolves the name of this
                     * interface to the same Class object.
                     */
                    Class<?> interfaceClass = null;
                    try {
                        interfaceClass = Class.forName(intf.getName(), false, loader);
                    } catch (ClassNotFoundException e) {
                    }
                    if (interfaceClass != intf) {
                        throw new IllegalArgumentException(
                            intf + " is not visible from class loader");
                    }
                    /*
                     * Verify that the Class object actually represents an
                     * interface.
                     */
                    if (!interfaceClass.isInterface()) {
                        throw new IllegalArgumentException(
                            interfaceClass.getName() + " is not an interface");
                    }
                    /*
                     * Verify that this interface is not a duplicate.
                     */
                    if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
                        throw new IllegalArgumentException(
                            "repeated interface: " + interfaceClass.getName());
                    }
                }
    
                String proxyPkg = null;     // package to define proxy class in
                int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
    
                /*
                 * Record the package of a non-public proxy interface so that the
                 * proxy class will be defined in the same package.  Verify that
                 * all non-public proxy interfaces are in the same package.
                 */
                for (Class<?> intf : interfaces) {
                    int flags = intf.getModifiers();
                    if (!Modifier.isPublic(flags)) {
                        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 + ".";
                }
    
                /*
                 * Choose a name for the proxy class to generate.
                 */
                long num = nextUniqueNumber.getAndIncrement();
                String proxyName = proxyPkg + proxyClassNamePrefix + num;
    
                /*
                 * Generate the specified proxy class.
                 */
                byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
                    proxyName, interfaces, accessFlags);
                try {
                    return defineClass0(loader, proxyName,
                                        proxyClassFile, 0, proxyClassFile.length);
                } catch (ClassFormatError e) {
                    /*
                     * A ClassFormatError here means that (barring bugs in the
                     * proxy class generation code) there was some other
                     * invalid aspect of the arguments supplied to the proxy
                     * class creation (such as virtual machine limitations
                     * exceeded).
                     */
                    throw new IllegalArgumentException(e.toString());
                }
            }
    }

    直接画重点:

    byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
                    proxyName, interfaces, accessFlags);
    
    return defineClass0(loader, proxyName,
                                        proxyClassFile, 0, proxyClassFile.length);

    调用ProxyGenerator.generateProxyClass最终动态生成一个代理类,但是似乎并未找到何处调用了invoke方法;参考CSDN: https://blog.csdn.net/jiankunking/article/details/52143504这边文章,尝试将这个动态生成的二进制字节码输出到本地,并反编译出来一看究竟,测试代码如下:

    public class AopTest {
        @Test
        public void Testdynamicproxy() {
    
            OrderServiceImpl serviceImpl = new OrderServiceImpl();
            OrderLogger logger = new OrderLogger();
            OrderService service = (OrderService) new ServiceProxy(serviceImpl, logger).GetDynamicProxy();
            service.createOrder();
            //输出动态代理类字节码
            createProxyClassFile();
        }
    
        private static void createProxyClassFile(){  
            String name = "ProxyObject";  
            byte[] data = ProxyGenerator.generateProxyClass(name,new Class[]{OrderService.class});  
            FileOutputStream out =null;  
            try {  
                out = new FileOutputStream(name+".class");  
                System.out.println((new File("hello")).getAbsolutePath());  
                out.write(data);  
            } catch (FileNotFoundException e) {  
                e.printStackTrace();  
            } catch (IOException e) {  
                e.printStackTrace();  
            }finally {  
                if(null!=out) try {  
                    out.close();  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  
            }  
        } 
    }

    使用java Decompiler工具将这个二进制class文件反编译查看:

    具体动态代理类ProxyObject.java:

    import com.sl.aop.OrderService;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.lang.reflect.UndeclaredThrowableException;
    
    public final class ProxyObject
      extends Proxy
      implements OrderService
    {
      private static Method m1;
      private static Method m2;
      private static Method m3;
      private static Method m0;
      
      public ProxyObject(InvocationHandler paramInvocationHandler)
      {
        super(paramInvocationHandler);
      }
      
      public final boolean equals(Object paramObject)
      {
        try
        {
          return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
        }
        catch (Error|RuntimeException localError)
        {
          throw localError;
        }
        catch (Throwable localThrowable)
        {
          throw new UndeclaredThrowableException(localThrowable);
        }
      }
      
      public final String toString()
      {
        try
        {
          return (String)this.h.invoke(this, m2, null);
        }
        catch (Error|RuntimeException localError)
        {
          throw localError;
        }
        catch (Throwable localThrowable)
        {
          throw new UndeclaredThrowableException(localThrowable);
        }
      }
      
      public final void createOrder()
      {
        try
        {
          this.h.invoke(this, m3, null);
          return;
        }
        catch (Error|RuntimeException localError)
        {
          throw localError;
        }
        catch (Throwable localThrowable)
        {
          throw new UndeclaredThrowableException(localThrowable);
        }
      }
      
      public final int hashCode()
      {
        try
        {
          return ((Integer)this.h.invoke(this, m0, null)).intValue();
        }
        catch (Error|RuntimeException localError)
        {
          throw localError;
        }
        catch (Throwable localThrowable)
        {
          throw new UndeclaredThrowableException(localThrowable);
        }
      }
      
      static
      {
        try
        {
          m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
          m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
          m3 = Class.forName("com.sl.aop.OrderService").getMethod("createOrder", new Class[0]);
          m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
          return;
        }
        catch (NoSuchMethodException localNoSuchMethodException)
        {
          throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
        }
        catch (ClassNotFoundException localClassNotFoundException)
        {
          throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
        }
      }

    终于看到关于invoke的部分了:

    public final void createOrder()
      {
        try
        {
          this.h.invoke(this, m3, null);
          return;
        }
        catch (Error|RuntimeException localError)
        {
          throw localError;
        }
        catch (Throwable localThrowable)
        {
          throw new UndeclaredThrowableException(localThrowable);
        }
      }

    实际上动态代理类继承自Proxy,并且实现了目标类继承的接口,在createOrder方法中调用了invoke方法,实现了切面逻辑的植入,这里也回答了一个问题,为什么JDK动态代理的目标类必须是实现接口的,因为代理类其实是针对接口代理,而不是针对类来代理的,动态代理类自己继承自Proxy,Java也不允许多重继承。动态代理类和目标类其实是各自实现了接口,代理类通过InvocationHandler.invoke实现对目标类方法的调用。

    CGLIB动态代理

    CGLIB代理是通过使用一个字节码处理框架ASM,来转换字节码并生成新的类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,实现织如如横切逻辑 ,效率上比使用反射技术的JDK动态代理要高,但是由于CGLIB的原理是动态为目标类生成子类代理类,所以不能为声明为final的方法进行代理。其使用主要涉及两个类:

    MethodInterceptor接口:该接口提供一个方法intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3)主要用于拦截目标类方法的调用

            Object arg0, :被代理的目标类

               Method arg1, 委托方法

            Object[] arg2, 方法参数

            MethodProxy arg3 :代理方法的MethodProxy对象

    Enhancer类:用于创建代理类

    示例:

    实现MethodInterceptor接口,代理类在调用方法时,CGLIB会回调MethodInterceptor接口intercept方法,从而织入切面逻辑。

    package com.sl.aop;
    import java.lang.reflect.Method;
    import org.springframework.cglib.proxy.Enhancer;
    import org.springframework.cglib.proxy.MethodInterceptor;
    import org.springframework.cglib.proxy.MethodProxy;
    
    public class CglibServiceProxy implements MethodInterceptor {
    
        private Object targetClass;
        private OrderLogger orderLogger;
        
        
        public CglibServiceProxy(Object targetClass,OrderLogger orderLogger) {
            this.targetClass = targetClass;
            this.orderLogger = orderLogger;
        }
        /** 
         * 创建代理对象 
         *
         */  
        public Object getInstance() { 
            Enhancer enhancer = new Enhancer();  
            
            //设置目标类(需要被代理的类)  
            enhancer.setSuperclass(this.targetClass.getClass());
            
            // 回调方法  
            enhancer.setCallback(this);
            
            // 创建代理对象  
            return enhancer.create();  
        }  
      
        /** 
         * 拦截所有目标类方法的调用 
         *
         */
        @Override
        public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
            orderLogger.beforeCreateOrder();  
            
            Object o1 = arg3.invokeSuper(arg0, arg2);
            
            orderLogger.afterCreateOrder();  
            return o1;  
        }
    }

    测试方法:

    public void Testdynamicproxy() {
            System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\class");
            OrderServiceImpl serviceImpl = new OrderServiceImpl();
            OrderLogger logger = new OrderLogger();
            CglibServiceProxy proxy = new CglibServiceProxy(serviceImpl,logger);  
              //通过生成子类的方式创建代理类  
            OrderServiceImpl proxyImp = (OrderServiceImpl)proxy.getInstance();
            proxyImp.createOrder();
            
        }

    结果:

     

    System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\class");将cglib动态代理类输出到指定目录,反编译查看一下代理类真面目:

    package com.sl.aop;
    import com.sl.aop.OrderServiceImpl;
    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 OrderServiceImpl$$EnhancerByCGLIB$$17779aa4 extends OrderServiceImpl 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$createOrder$0$Method;
       private static final MethodProxy CGLIB$createOrder$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.sl.aop.OrderServiceImpl$$EnhancerByCGLIB$$17779aa4");
          Class var1;
          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");
          CGLIB$createOrder$0$Method = ReflectUtils.findMethods(new String[]{"createOrder", "()V"}, (var1 = Class.forName("com.sl.aop.OrderServiceImpl")).getDeclaredMethods())[0];
          CGLIB$createOrder$0$Proxy = MethodProxy.create(var1, var0, "()V", "createOrder", "CGLIB$createOrder$0");
       }
    
       final void CGLIB$createOrder$0() {
          super.createOrder();
       }
    
       public final void createOrder() {
          MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
          if(this.CGLIB$CALLBACK_0 == null) {
             CGLIB$BIND_CALLBACKS(this);
             var10000 = this.CGLIB$CALLBACK_0;
          }
    
          if(var10000 != null) {
             var10000.intercept(this, CGLIB$createOrder$0$Method, CGLIB$emptyArgs, CGLIB$createOrder$0$Proxy);
          } else {
             super.createOrder();
          }
       }
    
       final boolean CGLIB$equals$1(Object var1) {
          return super.equals(var1);
       }
    
       public final boolean equals(Object var1) {
          MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
          if(this.CGLIB$CALLBACK_0 == 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).booleanValue();
          } else {
             return super.equals(var1);
          }
       }
    
       final String CGLIB$toString$2() {
          return super.toString();
       }
    
       public final String toString() {
          MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
          if(this.CGLIB$CALLBACK_0 == 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(this.CGLIB$CALLBACK_0 == 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(this.CGLIB$CALLBACK_0 == 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 -2138148221:
             if(var10000.equals("createOrder()V")) {
                return CGLIB$createOrder$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 OrderServiceImpl$$EnhancerByCGLIB$$17779aa4() {
          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;
       }
    
       private static final void CGLIB$BIND_CALLBACKS(Object var0) {
          OrderServiceImpl$$EnhancerByCGLIB$$17779aa4 var1 = (OrderServiceImpl$$EnhancerByCGLIB$$17779aa4)var0;
          if(!var1.CGLIB$BOUND) {
             var1.CGLIB$BOUND = true;
             Object var10000 = CGLIB$THREAD_CALLBACKS.get();
             if(var10000 == null) {
                var10000 = CGLIB$STATIC_CALLBACKS;
                if(CGLIB$STATIC_CALLBACKS == null) {
                   return;
                }
             }
    
             var1.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])var10000)[0];
          }
    
       }
    
       public Object newInstance(Callback[] var1) {
          CGLIB$SET_THREAD_CALLBACKS(var1);
          OrderServiceImpl$$EnhancerByCGLIB$$17779aa4 var10000 = new OrderServiceImpl$$EnhancerByCGLIB$$17779aa4();
          CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
          return var10000;
       }
    
       public Object newInstance(Callback var1) {
          CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});
          OrderServiceImpl$$EnhancerByCGLIB$$17779aa4 var10000 = new OrderServiceImpl$$EnhancerByCGLIB$$17779aa4();
          CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
          return var10000;
       }
    
       public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
          CGLIB$SET_THREAD_CALLBACKS(var3);
          OrderServiceImpl$$EnhancerByCGLIB$$17779aa4 var10000 = new OrderServiceImpl$$EnhancerByCGLIB$$17779aa4;
          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();
       }
    }

    上面的代码可以看到代理类OrderServiceImpl$$EnhancerByCGLIB$$17779aa4 继承目标类OrderServiceImpl并且实现了接口Factory,代理类中关于createorder生成了两个方法CGLIB$createOrder$0和createOrder:

    CGLIB$createOrder$0方法内部直接调用目标类的supper.createOrder

    createOrder方法内部首先盘点否实现了MethodInterceptor接口的callback,如果存在则调用MethodInterceptor接口拦截方法intercept,根据前面的实现intercept方法内部实现了对目标方法的调用Object o1 = arg3.invokeSuper(arg0, arg2),invokeSuper内部实际上是直接调用的代理类的CGLIB$createOrder$0()方法,最终调用了目标类createOrder。

    两种代理对比

    JDK动态代理:

    代理类与委托类实现同一接口,主要是通过代理类实现InvocationHandler并重写invoke方法来进行动态代理的,在invoke方法中将对方法进行增强处理  优点:不需要硬编码接口,代码复用率高,缺点:只能够代理实现了接口的委托类 

    CGLIB动态代理:

    代理类将委托类作为自己的父类并为其中的非final委托方法创建两个方法,一个是与委托方法签名相同的方法,它在方法中会通过super调用委托方法;另一个是代理类独有的方法。在代理方法中,它会判断是否存在实现了MethodInterceptor接口的对象,若存在则将调用intercept方法对委托方法进行代理  优点:可以在运行时对类或者是接口进行增强操作,且委托类无需实现接口,缺点:不能对final类以及final方法进行代理


  • 相关阅读:
    相册 垂直居中; 水平居中. 1)宽度 大于高度, 宽度 100%; 2) 高度 大于 宽度 , 高度100%; getimagesize , list --->line-height , text-align, vertical-align, max-height, max-width
    PHPexcel 导入import 数据到 mysql: mysql 查询数据是否存在, 如果存在返回id, 不存在, 插入返回id. 2) mysql_query , mysql_connect, mysql_select_db, mysql_error, mysql_num_rows,mysql_close
    css 利用border 绘制三角形. triangle
    css 1) calc() 函数的使用. 2)box-sizing:border-box
    css 实现省略号. text-overflow: ellipsis; 同时设置四个属性才可以.
    table 表头固定 thead固定. 1) 使用jquery.freezeheader.js
    MapReduce的Shuffle机制
    MapReduce的ReduceTask执行机制
    MapReduce的MapTask执行机制
    MapReduce逻辑切片规则
  • 原文地址:https://www.cnblogs.com/ashleyboy/p/9027072.html
Copyright © 2020-2023  润新知