动态代理简析

代理模式

  • 一个抽象接口,一个功能类,一个功能类的代理类。代理类组合功能类。功能类和功能类的代理均实现了抽象接口。调用者通过代理类调用实际功能类。
  • 代理分为静态代理和动态代理。动态代理的经典使用:Retrofit开源库。
  • 1、和适配器模式的区别:适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口。
    2、和装饰器模式的区别:装饰器模式为了增强功能,而代理模式是为了加以控制。
  • 应用场景:远程代理(服务器和客户端)、安全代理(安全控制)、虚拟代理、延迟加载、智能指引。

请添加图片描述

动态代理

动态代理实现流程

  1. 自定义一个interface接口。动态代理只能对接口代理,因为代理类是继承了Proxy类的。
  2. 自定义Handler类,扩展实现InvocationHandler接口,实现invoke方法。
  3. 通过Proxy.newProxyInstance获得动态代理类实例proxy。第一个参数是interface的classLoader,第二个参数是interface的class,第三个参数是步骤二的对象实例。
  4. proxy是实现了interface接口的,即可调用interface的方法。此时调用interface的方法最终是调用到步骤二中InvocationHandler中的invoke方法。

动态代理中的角色

  • interface是代理模式中的抽象接口。
  • InvocationHandler是代理模式中的实际功能类(RealClass)的角色。
  • Proxy.newProxyInstance函数内部会在JVM内生成代理类,即代理模式中的代理类ProxyClass; 函数返回结果是代理类的一个实例对象,相当于client中的proxyClassObject

获取Proxy代理类。

  • getProxyClass(ClassLoader loader, Class<?>... interfaces) 获取代理类class类型,可以通过这个class类型,反射构造函数,创建实例。

newProxyInstance方法解析

  1. 生成代理类。通过getProxyClass0方法生成代理类。这个函数可以生成一个$Proxy0.class文件,并且当做代理类加载到JVM中。
  2. 通过反射获取代理类构造函数。构造函数的入参是InvocationHandler
  3. 通过构造函数生成代理类实例。
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
    throws IllegalArgumentException
{
    
    
    Objects.requireNonNull(h);
    final Class<?>[] intfs = interfaces.clone();
    // 省略......
    /*
     * Look up or generate the designated proxy class.
     */
    Class<?> cl = getProxyClass0(loader, intfs); // 步骤1。核心步骤,生成class类,并让JVM加载。

    /*
     * Invoke its constructor with the designated invocation handler.
     */
    try {
    
    
        // 省略......
        final Constructor<?> cons = cl.getConstructor(constructorParams); // 步骤2 获取构造函数
        final InvocationHandler ih = h;
        if (!Modifier.isPublic(cl.getModifiers())) {
    
    
            cons.setAccessible(true);
        }
        return cons.newInstance(new Object[]{
    
    h}); // 步骤3 new 一个代理类实例
    } catch (IllegalAccessException|InstantiationException e) {
    
    
        throw new InternalError(e.toString(), e);
    } catch (InvocationTargetException e) {
    
    
        // 省略......
    } catch (NoSuchMethodException e) {
    
    
        throw new InternalError(e.toString(), e);
    }
}

标准JVM虚拟机中getProxyClass0 函数实现

  • 生成动态class类的核心实现是Proxy.ProxyClassFactory#apply方法。调用ProxyGenerator.generateProxyClass(final String name, Class<?>[] interfaces, int accessFlags)方法。
  • generateProxyClass的原理大概就是解析interface接口内定义的方法,然后通过字符拼接或者写文件(文件名 $Proxy0.class)的方式,生成class文件,加载到JVM中,生成代理类。
  • ProxyGenerator类源码链接:https://github.com/JetBrains/jdk8u_jdk/blob/master/src/share/classes/sun/misc/ProxyGenerator.java
  • 系统生成的代理类。下面的$Proxy0的代码并非真实从jvm的生成的动态代理class文件反编译生成的,而是参考其他博主的文章,大概写了一下,便于理解系统生成的代理类。
// 自定义一个接口
public interface NameInterface {
    
    
    String getName();
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

 // 这个类不是实际反编译的类,和实际系统生成的类有出入
 // 反编译类继承了Proxy类(动态代理只能代理接口),并且实现了抽象接口。
public final class $Proxy0 extends Proxy implements NameInterface {
    
    
    private static Method m1;
    private static Method m3; //m3代表接口方法,静态块中赋值
    private static Method m2;
    private static Method m0;

    // java.lang.reflect.Proxy#Proxy(java.lang.reflect.InvocationHandler)
    // 父类Proxy组合了一个InvocationHandler对象
    public $Proxy0(InvocationHandler paramInvocationHandler) throws {
    
    
        super(paramInvocationHandler);
    }

    static {
    
    
        try {
    
    
            m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{
    
    Class.forName("java.lang.Object")});
            m3 = Class.forName("NameInterface").getMethod("getName", new Class[0]); // 反射了接口Method,作为invoke函数的入参
            m2 = Class.forName("java.lang.Object").getMethod("toString", 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());
        }
    }

    @Override
    public String getName() throws {
    
    
        try {
    
    
            return (String) this.h.invoke(this, m3, null); // 调用InvocationHandler的invoke方法
        } catch (Error | RuntimeException localError) {
    
    
            throw localError;
        } catch (Throwable localThrowable) {
    
    
            throw new UndeclaredThrowableException(localThrowable);
        }
    }
    // 还有其他的equals、hashcode、toString方法。
}

Android虚拟机中getProxyClass0 函数实现

  • 核心实现:生成动态class类的核心实现是Proxy.ProxyClassFactory#apply方法。调用native方法 Proxy#generateProxy,生成代理类。
/**
 * A factory function that generates, defines and returns the proxy class given
 * the ClassLoader and array of interfaces.
 */
private static final class ProxyClassFactory implements BiFunction<ClassLoader, Class<?>[], Class<?>>
{
    
    
    // prefix for all proxy class names
    private static final String proxyClassNamePrefix = "$Proxy";

    // next number to use for generation of unique proxy class names
    private static final AtomicLong nextUniqueNumber = new AtomicLong();

    @Override
    public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
    
    
        //省略部分代码.....   for循环校验interfaces 合法性
        //省略部分代码..... for循环遍历非public的接口类,确保所有非public接口是同包名下的
        {
    
    
            // Android-changed: Generate the proxy directly instead of calling
            // through to ProxyGenerator.
            List<Method> methods = getMethods(interfaces);
            Collections.sort(methods, ORDER_BY_SIGNATURE_AND_SUBTYPE);
            validateReturnTypes(methods);
            List<Class<?>[]> exceptions = deduplicateAndGetExceptions(methods);

            Method[] methodsArray = methods.toArray(new Method[methods.size()]);
            Class<?>[][] exceptionsArray = exceptions.toArray(new Class<?>[exceptions.size()][]);

            /*
             * Choose a name for the proxy class to generate.
             */
            long num = nextUniqueNumber.getAndIncrement();
            String proxyName = proxyPkg + proxyClassNamePrefix + num; //包名 + 类名 + 数字

            return generateProxy(proxyName, interfaces, loader, methodsArray, exceptionsArray);
        }
    }
}
  • 函数流程:Proxy#getProxyClass0 -> WeakCache#get -> WeakCache.Factory#Factory -> WeakCache.Factory#get -> Proxy.ProxyClassFactory#apply -> Proxy#generateProxy -> native方法Proxy_generateProxy
  • WeakCache#subKeyFactory类型是Proxy.KeyFactory;WeakCache#valueFactory类型是Proxy.ProxyClassFactory; WeakCache.Factory继承了function.Supplier;
// java.lang.reflect.Proxy
/**
 * a cache of proxy classes
 */
private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
    proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
  • generateProxy native实现Android系统源码:art/runtime/native/java_lang_reflect_Proxy.cc
static jclass Proxy_generateProxy(JNIEnv* env, jclass, jstring name, jobjectArray interfaces,
                                  jobject loader, jobjectArray methods, jobjectArray throws) {
    
    
  ScopedFastNativeObjectAccess soa(env);
  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
  return soa.AddLocalReference<jclass>(class_linker->CreateProxyClass(
      soa, name, interfaces, loader, methods, throws));
}
// JNI动态注册
static JNINativeMethod gMethods[] = {
    
    
  FAST_NATIVE_METHOD(Proxy, generateProxy, "(Ljava/lang/String;[Ljava/lang/Class;Ljava/lang/ClassLoader;[Ljava/lang/reflect/Method;[[Ljava/lang/Class;)Ljava/lang/Class;"),
};

void register_java_lang_reflect_Proxy(JNIEnv* env) {
    
    
  REGISTER_NATIVE_METHODS("java/lang/reflect/Proxy");
}
  • art/runtime/class_linker.cc 源码文件中定义了ClassLinker::CreateProxyClass,此方法是Android生成class代理类的核心方法。
mirror::Class* ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRunnable& soa,
                                             jstring name,
                                             jobjectArray interfaces,
                                             jobject loader,
                                             jobjectArray methods,
                                             jobjectArray throws)

猜你喜欢

转载自blog.csdn.net/followYouself/article/details/120242621