用法
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 方法,在这个方法中去反射调用对应的方法。