• JDK动态代理深入剖析


    1 基于接口的代理模式#

    什么是代理?

    简单来说,代理是指一个对象代替另一个对象去做某些事情。

    例如,对于每个程序员来说,他都有编程的能力:

    interface Programmable {
        void developSoftware();
    }
    

    对于Java程序员,他会编写Java代码:

    class JavaProgrammer implements Programmable {
        @Override
        public void developSoftware() {
            System.out.println("编写Java代码");
        }
    }
    

    对于JavaScript程序员,他会编写JavaScript代码:

    class JavaScriptProgrammer implements Programmable {
        @Override
        public void developSoftware() {
            System.out.println("编写JavaScript代码");
        }
    }
    

    ……

    为了完成一个商业软件,需要各种程序员共同协作。

    因此,互联网公司出现了:

    class ITCompany implements Programmable {
        private List programmers = new LinkedList<>();
    
        public void recruitProgrammer(Programmable programmer) {
            programmers.add(programmer);
        }
        
        @Override
        public void developSoftware() {
            designProduct();
            programmers.forEach(Programmable::developSoftware);
            operate();
        }
        
        public void designProduct() {
            System.out.println("产品设计");
        }
        
        public void operate() {
            System.out.println("上线运营");
        }
    }
    

    此时,互联网公司对程序员进行了代理,并通过提供额外的功能,完善了善软件开发流程:产品设计 → 编写代码 → 上线运营等。

    ITCompany company = new ITCompany();
    company.recruitProgrammer(new JavaProgrammer());
    company.recruitProgrammer(new JavaScriptProgrammer());
    company.developSoftware();
    

    输出如下:

    产品设计
    编写Java代码
    编写JavaScript代码
    上线运营
    

    总结类图如下:

    接口静态代理模式.drawio

    以上方式被称为静态代理模式,步骤如下:

    1. 实现被代理接口。
    2. 保存被代理对象。
    3. 自定义增强方法。
    4. 实现被代理的方法。

    2 JDK动态代理-Proxy#

    静态代理有一个明显的局限性,那就是它只能固定代理某一类接口。如果需要代理其他接口,就必须重新编写一个代理类。

    java.lang.reflect.Proxy提供了一系列创建动态代理类和实例的静态方法。

    例如,为了创建Programmable接口的代理类,可以按如下方式:

    // 1、自定义增强方法
    InvocationHandler handler = new MyInvocationHandler();
    // 2、创建代理类
    Class proxyClass = Proxy.getProxyClass(Programmable.class.getClassLoader(), Programmable.class);
    // 3、创建代理对象
    Programmable p = (Programmable) proxyClass.getConstructor(InvocationHandler.class).newInstance(handler);
    

    或者:

    Programmable p = (Programmable) Proxy.newProxyInstance(Programmable.class.getClassLoader(),
                                                           new Class[] { Programmable.class },
                                                           handler);
    

    很明显,第二种方式更加简便(推荐使用)。它其实是对第一种方式进行了封装,并且做了许多安全处理:

    public static Object newProxyInstance(ClassLoader loader,
                                          Class[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
    {
        // 1、安全检查
        Objects.requireNonNull(h);
        final Class[] intfs = interfaces.clone();
        final SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
        }
    
        // 2、根据接口创建代理类(如果已存在,会直接返回之前创建的代理类)
        Class cl = getProxyClass0(loader, intfs);
    
        // 3、实例化代理对象
        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) {
        }
    }
    

    我们可以发现,Proxy创建代理对象的核心步骤有两步:

    1. 创建代理类。
    2. 实例化代理对象。

    2.1 创建代理类#

    创建代理类核心方法为java.lang.reflect.Proxy#getProxyClass0

    private static Class getProxyClass0(ClassLoader loader, Class... interfaces) {
        if (interfaces.length > 65535) {
            throw new IllegalArgumentException("interface limit exceeded");
        }
        return proxyClassCache.get(loader, interfaces);
    }
    
    • java.lang.reflect.Proxy#proxyClassCache成员变量中会缓存已创建的代理类(key: 类加载器, parameter: 接口对象数组, value: 代理类对象)。

      private static final WeakCache[], Class>
          proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
      
    • WeakCache#get()方法中会调用到如下代码:V value = supplier.get();,进而执行valueFactory.apply(key, parameter)。其中valueFactoryProxyClassFactory对象。

    ProxyClassFactory#apply()方法中才会真正创建代理类:

    public Class apply(ClassLoader loader, Class[] interfaces) {
        // 1、校验interfaces
        Map, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
        for (Class intf : interfaces) {
            // 1.1、接口?重复?类加载器可访问?
        }
        String proxyPkg = null;     // package to define proxy class in
        for (Class intf : interfaces) {
            // 1.2、non-public接口是否在同一个包下
        }
    
        // 2、生成包名
        if (proxyPkg == null) {
           	// if no non-public proxy interfaces, use com.sun.proxy package
        	proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
        }
        long num = nextUniqueNumber.getAndIncrement();
        String proxyName = proxyPkg + proxyClassNamePrefix + num;	// 包名 + $Proxy + 递增数字
    
        // 3、生成代理类class文件
        byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces, accessFlags);
        try {
            // 4、动态加载代理类
            return defineClass0(loader, proxyName,proxyClassFile, 0, proxyClassFile.length);
        } catch (ClassFormatError e) {
        }
    }
    

    核心在于ProxyGenerator#generateProxyClass()

    public static byte[] generateProxyClass(final String proxyName, Class[] interfaces, int accessFlags) {
        ProxyGenerator proxyGenerator = new ProxyGenerator(proxyName, interfaces, accessFlags);
        // 生成class文件
        final byte[] clzBytes = proxyGenerator.generateClassFile();
        if (saveGeneratedFiles) {
            // 保存class文件
        }
        return clzBytes;
    }
    

    proxyGenerator#generateClassFile()中生成.class文件:

    private byte[] generateClassFile() {
        // 1、添加Object中的方法到proxyMethods缓存:hashCode()、equals()、toString()
        this.addProxyMethod(hashCodeMethod, Object.class);
        this.addProxyMethod(equalsMethod, Object.class);
        this.addProxyMethod(toStringMethod, Object.class);
        // 2、添加interfaces中的方法到proxyMethods缓存
        Class[] interfaces = this.interfaces;
        int interfacesLength = interfaces.length;
        int i;
        Class interfaceClz;
        for(i = 0; i < interfacesLength; ++i) {
            interfaceClz = interfaces[i];
            Method[] methods = interfaceClz.getMethods();
            int methodsLength = methods.length;
            for(int index = 0; index < methodsLength; ++index) {
                Method m = methods[index];
                this.addProxyMethod(m, interfaceClz);
            }
        }
        try {
            // 3、生成构造函数(形参为:InvocationHandler),添加到methods缓存
            this.methods.add(this.generateConstructor());
            proxyMethodsIterator = this.proxyMethods.values().iterator();
            while(proxyMethodsIterator.hasNext()) {
                proxyMethodList = (List)proxyMethodsIterator.next();
                iterator = proxyMethodList.iterator();
                while(iterator.hasNext()) {
                    ProxyGenerator.ProxyMethod proxyMethod = (ProxyGenerator.ProxyMethod)iterator.next();
                    // 4、生成代理方法成员变量,变量名为m[n],类型为Method,添加到fields缓存
                    this.fields.add(new ProxyGenerator.FieldInfo(proxyMethod.methodFieldName, "Ljava/lang/reflect/Method;", 10));
                    /* 	5、生成代理方法,添加到methods缓存。
                    	代理方法执行逻辑:
                    		创建变量:InvocationHandler对象/当前Method对象/方法原有形参,
                    		执行InvocationHandler.invoke()方法
                    */
                    this.methods.add(proxyMethod.generateMethod());
                }
            }
            // 6、生成静态初始化方法(没有形参)
            this.methods.add(this.generateStaticInitializer());
        } catch (IOException interfaces0) {}
    
        if (this.methods.size() > 65535) {} else if (this.fields.size() > 65535) {
        } else {
            // 7、生成类名
            this.cp.getClass(dotToSlash(this.className));
            // 8、继承父类:Proxy
            this.cp.getClass("java/lang/reflect/Proxy");
            // 9、实现所有接口
            interfaces = this.interfaces;
            interfacesLength = interfaces.length;
            for(i = 0; i < interfacesLength; ++i) {
                interfaceClz = interfaces[i];
                this.cp.getClass(dotToSlash(interfaceClz.getName()));
            }
            // 10、写出到字节流
            this.cp.setReadOnly();
            ByteArrayOutputStream byteArrOutput = new ByteArrayOutputStream();
            DataOutputStream dataOutput = new DataOutputStream(byteArrOutput);
            try {
                dataOutput.writeInt(-889275714);
                dataOutput.writeShort(0);
                dataOutput.writeShort(49);
                this.cp.write(dataOutput);
                // 访问修饰符
                dataOutput.writeShort(this.accessFlags);
                // 类名
                dataOutput.writeShort(this.cp.getClass(dotToSlash(this.className)));
                // 父类:Proxy
                dataOutput.writeShort(this.cp.getClass("java/lang/reflect/Proxy"));
                // 接口
                dataOutput.writeShort(this.interfaces.length);
                Class[] interfacesArr = this.interfaces;
                int interfacesArrLen = interfacesArr.length;
                for(int i = 0; i < interfacesArrLen; ++i) {
                    Class interfaceClz = interfacesArr[i];
                    dataOutput.writeShort(this.cp.getClass(dotToSlash(interfaceClz.getName())));
                }
                // 成员变量:即代理方法名-Method
                dataOutput.writeShort(this.fields.size());
                iterator = this.fields.iterator();
                while(iterator.hasNext()) {
                    ProxyGenerator.FieldInfo f = (ProxyGenerator.FieldInfo)iterator.next();
                    f.write(dataOutput);
                }
                // 代理方法:重新编写执行逻辑后的方法
                dataOutput.writeShort(this.methods.size());
                iterator = this.methods.iterator();
                while(iterator.hasNext()) {
                    ProxyGenerator.MethodInfo m = (ProxyGenerator.MethodInfo)iterator.next();
                    m.write(dataOutput);
                }
                dataOutput.writeShort(0);
                return byteArrOutput.toByteArray();
            } catch (IOException var9) {
            }
        }
    }
    

    因此,java.lang.reflect.Proxy#getProxyClass0的核心作用如下:

    • 如果缓存中,由类加载器loader加载,并且实现给定接口interfaces的代理类已经存在,会直接返回该代理类。
    • 如果代理类不存在,会使用ProxyClassFactory创建新的代理类。

    例如,对于某些接口:

    public interface IT1 {
        void fun1();
    }
    public interface IT2 {
        Object fun2(Object[] args);
    }
    

    生成代理类的伪代码如下:

    package com.sun.proxy|non-public接口所在包
    [public] final class $Proxy[n]
        extends Proxy
        implements IT1, IT2 {
        protected InvocationHandler h;	// Proxy类中
        private static Method m0;	// hashCode
        private static Method m1;	// equals
        private static Method m2;	// toString
        private static Method m3;	// fun1
        private static Method m4;	// fun2
        public void hashCode() {
            InvocationHandler handler = this.h;
            Method m = this.mo;
            handler.invoke(this, m, null);
        }
        public void equals(Object obj) {
            InvocationHandler handler = this.h;
            Method m = this.m1;
            handler.invoke(this, m, obj);
        }
        public void toString() {
            InvocationHandler handler = this.h;
            Method m = this.m2;
            handler.invoke(this, m, null);
        }
        public void fun1() {
            InvocationHandler handler = this.h;
            Method m = this.m3;
            handler.invoke(this, m, null);
        }
        public Object fun2(Object[] args) {
            InvocationHandler handler = this.h;
            Method m = this.m4;
            Object rs = handler.invoke(this, m, args);
            return rs;
        }
    }
    
    • 如果接口全为public,则代理类修饰符为public final。此时类名为com.sun.proxy.$Proxy[n]
    • 如果接口中存在non-public接口,且全位于同一个包下,则代理类修饰符为final。此时类名为non-public接口所在包.$Proxy[n]
    • 需要注意的是,Object对象中只有hashCode()equals()toString()这三个方法会被重写。
    • 动态生成的代理类修饰符为final,这意味着它不能被继承。

    例如,我们通过以下方式生成代理类,并打印出相关数据:

    Real real = new Real();
    Object proxyInstance = Proxy.newProxyInstance(ProxyDemo.class.getClassLoader(),
            new Class[]{IT1.class, IT2.class},
            new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    System.out.println("proxy method: " + method.getName());
                    return method.invoke(real, args);
                }
            });
    // 获取当前代理类的属性
    System.out.println("代理类成员变量:");
    Field[] fields = proxyInstance.getClass().getDeclaredFields();
    for (int i = 0; i < fields.length; i++) {
        StringBuilder sb = new StringBuilder();
        Field field = fields[i];
        // 修饰符
        int modifiers = field.getModifiers();
        sb.append(Modifier.toString(modifiers)).append(" ");
        field.setAccessible(true);
        // 成员变量类型&变量名
        sb.append(field.getType().getName()).append(" ").append(field.getName()).append(":");
        Method m = (Method) field.get(Method.class);
        m.setAccessible(true);
        // 方法名
        sb.append(m.getName());
        System.out.println(sb.toString());
    }
    System.out.println("Proxy类成员变量:");
    Field[] superFields = proxyInstance.getClass().getSuperclass().getDeclaredFields();
    for (int i = 0; i < superFields.length; i++) {
        StringBuilder sb = new StringBuilder();
        Field field = superFields[i];
        // 修饰符
        int modifiers = field.getModifiers();
        sb.append(Modifier.toString(modifiers)).append(" ");
        field.setAccessible(true);
        // 成员变量类型&变量名
        sb.append(field.getType().getName()).append(" ").append(field.getName());
        System.out.println(sb.toString());
    }
    System.out.println("代理类方法:");
    Method[] methods = proxyInstance.getClass().getMethods();
    for (int i = 0; i < methods.length; i++) {
        StringBuilder sb = new StringBuilder();
        Method method = methods[i];
        int modifiers = method.getModifiers();
        sb.append(Modifier.toString(modifiers)).append(" ");
        sb.append(method.getReturnType().getName()).append(" ").append(method.getName());
        System.out.println(sb.toString());
    }
    System.out.println("代理类构造函数:");
    Constructor[] constructors = proxyInstance.getClass().getConstructors();
    for (int i = 0; i < constructors.length; i++) {
        StringBuilder sb = new StringBuilder();
        Constructor constructor = constructors[i];
        int modifiers = constructor.getModifiers();
        sb.append(Modifier.toString(modifiers)).append(" ");
        sb.append(constructor.getName()).append("(");
        Class[] parameterTypes = constructor.getParameterTypes();
        for (int i1 = 0; i1 < parameterTypes.length; i1++) {
            sb.append(parameterTypes[i1].getName());
            if (i1 < parameterTypes.length - 1) {
                sb.append(",");
            }
        }
        sb.append(")");
        System.out.println(sb.toString());
    }
    

    打印结果如下:

    代理类成员变量:
    private static java.lang.reflect.Method m1:equals
    private static java.lang.reflect.Method m3:fun1
    private static java.lang.reflect.Method m2:toString
    private static java.lang.reflect.Method m4:fun2
    private static java.lang.reflect.Method m0:hashCode
    Proxy父类成员变量:
    private static final long serialVersionUID
    private static final [Ljava.lang.Class; constructorParams
    private static final java.lang.reflect.WeakCache proxyClassCache
    protected java.lang.reflect.InvocationHandler h
    private static final java.lang.Object key0
    代理类方法:
    public final boolean equals
    public final java.lang.String toString
    public final int hashCode
    public final void fun1
    public final java.lang.Object fun2
    public static boolean isProxyClass
    public static java.lang.reflect.InvocationHandler getInvocationHandler
    public static transient java.lang.Class getProxyClass
    public static java.lang.Object newProxyInstance
    public final void wait
    public final void wait
    public final native void wait
    public final native java.lang.Class getClass
    public final native void notify
    public final native void notifyAll
    代理类构造函数:
    public com.sun.proxy.$Proxy0(java.lang.reflect.InvocationHandler)
    

    2.2 实例化代理类对象#

    有了以上的基础,我们应该能很容易理解接下来的操作了。

    // 1、根据类型获取构造函数:形参为InvocationHandler
    final Constructor cons = cl.getConstructor(constructorParams);
    // 2、通过构造函数实例化代理对象,并返回
    final InvocationHandler ih = h;
    return cons.newInstance(new Object[]{h});
    

    2.3 总结#

    使用JDK-动态代理Proxy的方式如下:

    1. 实现InvocationHandler接口,其中invoke()方法为代理类实际执行的方法。
    2. 调用Proxy.newProxyInstance()方法,传入类加载器、代理接口数组和InvocationHandler对象。

    最终生成代理类的类图如下:

    JDK动态代理

    3 实例#

    3.1 Spring中的JDK动态代理#

    Spring使用org.springframework.aop.framework.ProxyFactoryBean进行AOP动态代理:

    public Object getObject() throws BeansException {
       initializeAdvisorChain();
       if (isSingleton()) {
          return getSingletonInstance();
       }
       else {
          if (this.targetName == null) {
             logger.info("Using non-singleton proxies with singleton targets is often undesirable. " +
                   "Enable prototype proxies by setting the 'targetName' property.");
          }
          return newPrototypeInstance();
       }
    }
    

    其最终会调用org.springframework.aop.framework.JdkDynamicAopProxy#getProxy(java.lang.ClassLoader)方法,进行JDK动态代理:

    public Object getProxy(@Nullable ClassLoader classLoader) {
       if (logger.isTraceEnabled()) {
          logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
       }
       return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
    }
    

    JdkDynamicAopProxy是Spring中JDK动态代理的核心类,它既作为动态代理的工具类,又作为InvocationHandler实现类定义了代理方法执行逻辑:

    final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
    

    其中实现的invoke()方法如下:

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
       Object oldProxy = null;
       boolean setProxyContext = false;
    
       TargetSource targetSource = this.advised.targetSource;
       Object target = null;
    
       try {
          if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
             // The target does not implement the equals(Object) method itself.
             return equals(args[0]);
          }
          else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
             // The target does not implement the hashCode() method itself.
             return hashCode();
          }
          else if (method.getDeclaringClass() == DecoratingProxy.class) {
             // There is only getDecoratedClass() declared -> dispatch to proxy config.
             return AopProxyUtils.ultimateTargetClass(this.advised);
          }
          else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
                method.getDeclaringClass().isAssignableFrom(Advised.class)) {
             // Service invocations on ProxyConfig with the proxy config...
             return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
          }
    
          Object retVal;
    
          if (this.advised.exposeProxy) {
             // Make invocation available if necessary.
             oldProxy = AopContext.setCurrentProxy(proxy);
             setProxyContext = true;
          }
    
          // Get as late as possible to minimize the time we "own" the target,
          // in case it comes from a pool.
          target = targetSource.getTarget();
          Class targetClass = (target != null ? target.getClass() : null);
    
          // Get the interception chain for this method.
          List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
    
          // Check whether we have any advice. If we don't, we can fallback on direct
          // reflective invocation of the target, and avoid creating a MethodInvocation.
          if (chain.isEmpty()) {
             // We can skip creating a MethodInvocation: just invoke the target directly
             // Note that the final invoker must be an InvokerInterceptor so we know it does
             // nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
             Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
             retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
          }
          else {
             // We need to create a method invocation...
             MethodInvocation invocation =
                   new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
             // Proceed to the joinpoint through the interceptor chain.
             retVal = invocation.proceed();
          }
    
          // Massage return value if necessary.
          Class returnType = method.getReturnType();
          if (retVal != null && retVal == target &&
                returnType != Object.class && returnType.isInstance(proxy) &&
                !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
             // Special case: it returned "this" and the return type of the method
             // is type-compatible. Note that we can't help if the target sets
             // a reference to itself in another returned object.
             retVal = proxy;
          }
          else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
             throw new AopInvocationException(
                   "Null return value from advice does not match primitive return type for: " + method);
          }
          return retVal;
       }
       finally {
          if (target != null && !targetSource.isStatic()) {
             // Must have come from TargetSource.
             targetSource.releaseTarget(target);
          }
          if (setProxyContext) {
             // Restore old proxy.
             AopContext.setCurrentProxy(oldProxy);
          }
       }
    }
    
    

    3.2 Mybatis中的JDK动态代理#

    org.apache.ibatis.session.SqlSession#getMapper可以获取动态生成的mapper实例:

     T getMapper(Class type);
    

    其底层会调用org.apache.ibatis.binding.MapperRegistry#getMapper

    public  T getMapper(Class type, SqlSession sqlSession) {
      final MapperProxyFactory mapperProxyFactory = (MapperProxyFactory) knownMappers.get(type);
      if (mapperProxyFactory == null) {
        throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
      }
      try {
        return mapperProxyFactory.newInstance(sqlSession);
      } catch (Exception e) {
        throw new BindingException("Error getting mapper instance. Cause: " + e, e);
      }
    }
    

    通过org.apache.ibatis.binding.MapperProxyFactory#newInstance(org.apache.ibatis.session.SqlSession)最终生成代理类:

    public T newInstance(SqlSession sqlSession) {
      final MapperProxy mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);
      return newInstance(mapperProxy);
    }
    
    protected T newInstance(MapperProxy mapperProxy) {
      return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
    }
    

    其中org.apache.ibatis.binding.MapperProxyInvocationHandler实现类,其invoke()方法如下:

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      try {
        if (Object.class.equals(method.getDeclaringClass())) {
          return method.invoke(this, args);
        } else {
          return cachedInvoker(method).invoke(proxy, method, args, sqlSession);
        }
      } catch (Throwable t) {
        throw ExceptionUtil.unwrapThrowable(t);
      }
    }
    
    private MapperMethodInvoker cachedInvoker(Method method) throws Throwable {
      try {
        return MapUtil.computeIfAbsent(methodCache, method, m -> {
          if (m.isDefault()) {
            try {
              if (privateLookupInMethod == null) {
                return new DefaultMethodInvoker(getMethodHandleJava8(method));
              } else {
                return new DefaultMethodInvoker(getMethodHandleJava9(method));
              }
            } catch (IllegalAccessException | InstantiationException | InvocationTargetException
                | NoSuchMethodException e) {
              throw new RuntimeException(e);
            }
          } else {
            return new PlainMethodInvoker(new MapperMethod(mapperInterface, method, sqlSession.getConfiguration()));
          }
        });
      } catch (RuntimeException re) {
        Throwable cause = re.getCause();
        throw cause == null ? re : cause;
      }
    }
    
    private MethodHandle getMethodHandleJava9(Method method)
        throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
      final Class declaringClass = method.getDeclaringClass();
      return ((Lookup) privateLookupInMethod.invoke(null, declaringClass, MethodHandles.lookup())).findSpecial(
          declaringClass, method.getName(), MethodType.methodType(method.getReturnType(), method.getParameterTypes()),
          declaringClass);
    }
    
    • 对于Object方法,它不会进行代理。
    • 对于非Object方法,会找到对应的Method对象,然后传入参数进行调用。
  • 相关阅读:
    每日一题:跳跃游戏II
    python基于php+MySQL的网络精品课程教学平台
    LabVIEW面向对象-面向对象
    【数据开发】DW数仓分层设计架构与同步策略(ODS、DWD、DWS等字段含义)
    【机器学习】K-means聚类分析
    项目适配 Oracle 改造的几点启示
    怎么开发一个快递便携电子秤方案
    fiddler的使用
    C++类的构造:简单的complex搭建
    QFile 类【官翻】
  • 原文地址:https://www.cnblogs.com/Xianhuii/p/16918191.html