源码阅读 | 动态代理

动态代理在静态代理的基础上提供了在运行时生成代理类的功能。因此相比于静态代理不用自定义代理类了。

用法

interface DemoListener {
    
    
    fun demo(str: String)
}
class TestDemo : DemoListener {
    
    
    override fun demo(str: String) {
    
    
        println(str)
    }
}

​ 一个接口,一个实现类,如果使用静态代理还需要创建一个代理类,在代理类中传入实现类,然后进行代理,这样就可以在调用接口方法的前后做一些改变了。

​ 如果是动态代理要怎么做呢?

fun main() {
    
    
    val testDemo = TestDemo()

    val proxy = Proxy.newProxyInstance(
        DemoListener::class.java.classLoader,
        arrayOf(DemoListener::class.java),
        CallBack(testDemo)
    ) as DemoListener

    proxy.demo("345")
}

class CallBack(val any: Any?) : InvocationHandler {
    
    
    override fun invoke(proxy: Any?, method: Method?, args: Array<out Any>?): Any? {
    
    
        println("代理前 -------->")
        if (any == null) {
    
    
            return null
        }
        val invoke = method?.invoke(any, args?.get(0))
        println("完成代理 -------->")
        return invoke
    }
}

​ 动态代理,这种是 java 已经弄好的,只需要调用方法即可。

​ 需要传入参数:classload ,接口 class 的数组,InvocationHandler 的实现。

​ 最终在使用 proxy 调用 demo 方法的时候会执行到 Callback 中的 invoke 方法中。其实 demo 方法还是你自己调用的,只不过用的是反射,好处就是在代理的前后,可以处理一些必须要处理的逻辑。并且可以进行健壮性的判断,例如被代理类是否为 null 等。

使用场景

​ 有些人会动态代理,但是不知道他的使用场景,经常在代码中不知道如果使用,下面说一个非常典型的案例:

​ 在 mvp 中,p 层 和 v 层需要进行交互。但是有一种情况比较棘手,如果 v 层被销毁了,p 层不知道,然后继续调用对应的方法,这种情况下就会导致空指针异常。

​ 解决:使用动态代理,在调用 v 层方法的前面判断一下 v 层是否为空即可

 /**
     * 动态代理,如果 V 层为 null。则取消调用
     *
     * @return
     */
    @Override
    public V getView() {
    
    
        if (proxy != null) return proxy;
        return proxy = (V) Proxy.newProxyInstance(
                viewRef.get().getClass().getClassLoader(),
                viewRef.get().getClass().getInterfaces(),
                this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    
        if (viewRef.get() != null && isArgs(args)) {
    
    
            return method.invoke(viewRef.get(), args);
        }
        return null;
    }

​ 其中 viewRef 为弱引用,里面存放着 v 层接口实例。

源码阅读

​ 1,到底干了什么,怎么实现的。

​ 2,学习一些源码怎么写的。

​ 3,如果不懂的代码没必要深究,发现偏了方向赶紧重新回到原点重新来


public static Object newProxyInstance(ClassLoader loader,
                                      Class<?>[] interfaces,
                                      InvocationHandler h)
    throws IllegalArgumentException
{
    
    
    Objects.requireNonNull(h);

    final Class<?>[] intfs = interfaces.clone();
 
    /*
     * 生成一个代理类  
     */
    Class<?> cl = getProxyClass0(loader, intfs);

    /*
     * Invoke its constructor with the designated invocation handler.
     */
    try {
    
    
      	
        //创建代理类 的构造函数
        final Constructor<?> cons = cl.getConstructor(constructorParams);
        final InvocationHandler ih = h;
        //判断如果不是 public 的则设置权限
        if (!Modifier.isPublic(cl.getModifiers())) {
    
    
            cons.setAccessible(true);
            // END Android-removed: Excluded AccessController.doPrivileged call.
        }
        //返回代理类的对象,
        return cons.newInstance(new Object[]{
    
    h});
    } catch (InvocationTargetException e) {
    
    
     	//........ 
    }
}

​ 上面首先生成了一个代理类,然后就调用代理类的构造,将 InvocationHandler 传了进去

​ 下面看一下代理类是怎样生成的

//代理缓存
private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
        proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());

//获取代理类
private static Class<?> getProxyClass0(ClassLoader loader,
                                       Class<?>... interfaces) {
    
    
    if (interfaces.length > 65535) {
    
    
        throw new IllegalArgumentException("interface limit exceeded");
    }

   //从缓存中获取代理
    return proxyClassCache.get(loader, interfaces);
}
public V get(K key, P parameter) {
    
    
	//...
    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) {
    
    
        //如果获取的是 null,创建一个新的 valuesMap
        ConcurrentMap<Object, Supplier<V>> oldValuesMap
            = map.putIfAbsent(cacheKey,
                              valuesMap = new ConcurrentHashMap<>());
        if (oldValuesMap != null) {
    
    
            valuesMap = oldValuesMap;
        }
    }

  	//调用 apply 方法生成代理类,subKey 就是代理类
    Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
    //从 map 中获取
    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;
            }
        }
       //创建工厂
        if (factory == null) {
    
    
            factory = new Factory(key, parameter, subKey, valuesMap);
        }
		
        //supplier 如果为空,则表示从 map 中没有获取到,下面进行保存
        //最终会循环到上面的return ,将 代理类返回出去
        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)) {
    
    
           
                supplier = factory;
            } else {
    
    
                supplier = valuesMap.get(subKey);
            }
        }
    }
}
@Override
    public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
    
    

        Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
        //遍历所有的接口
        for (Class<?> intf : interfaces) {
    
    
  
            Class<?> interfaceClass = null;
            try {
    
    
                // 加载一个 class 
                interfaceClass = Class.forName(intf.getName(), false, loader);
            } catch (ClassNotFoundException e) {
    
    
            }
           //判断 .....
            //将 加载出来的 class put 进去
            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;

        /*
         * 拿到包名
         */
        for (Class<?> intf : interfaces) {
    
    
            //获取修改,判断是否 public
            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) {
    
    
            // 如果没有非公共代理接口,则使用默认包。
            proxyPkg = "";
        }

        {
    
    
            //获取所有方法
            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();
            //代理名称,num 是标志,避免生成名字相同的代理名称
            // private static final String proxyClassNamePrefix = "$Proxy";
            String proxyName = proxyPkg + proxyClassNamePrefix + num;
			// 创建代理类
            return generateProxy(proxyName, interfaces, loader, methodsArray,
                                 exceptionsArray);
        }
    }
}

​ 梳理一下流程:

​ 首先调用 getProxyClass0 方法获取代理类,其中,首先会获取缓存,如果缓存不存在,则创建缓存。接着调用 apply 方法区生产一个代理类,在 apply 方法中会获取到包名,包名则是 proxyPak + $proxy+标志。 获取所有的方法,获取异常等,最终 通过 generateProxy 完成代理class 的床,generateProxy 是 native 层的方法。

​ 拿到 代理后将 InvocationHandler 传入到了代理中,由此我们可以推断 我们调用 newProxyInstance 返回代理类的方法的时候其实调用的就是 InvocationHandler 中的 invoke 方法。在 invoke 中 去反射调用我们需要调用的方法。

​ 总结一下:

​ 动态代理无非就是在程序运行的过程中动态的生成了一个 代理类,这个代理类接收一个接口。

​ 我们在调用 newProxyInstance 方法的时候就会传入一个 实现类。并且返回一个代理类

​ 我们在使用 代理类的时候会将其强转为对应的实现接口。然后在调用对应的方法,其实这里调用的是 实现类的 invoke 方法,在这个方法中去反射调用对应的方法。

Guess you like

Origin blog.csdn.net/baidu_40389775/article/details/106372965