AndroidStudio已经关了代理还走代理
三、动态代理
在2.1的静态代理代码中,如果现在需要扩展一个新的接口,那就需要分别在接口层、实际处理类、代理类中分别改动,如下所示:
// 1.首先定义接口层 interface ILogSender { public void sendLog(String log); }// 2.定义实现类 public class MainLogSender implements ILogSender {@Override public void sendLog(String log) { Log.d(“LogSender”, “MainLogSender send” + log); } }// 3.定义代理类 public class LogSenderProxy implements ILogSender { // 代理类持有被代理类的引用 private ILogSender mainLogSender = new MainLogSender();@Override public void sendLog(String log) { // 代理类需要完成的一些额外处理 Log.d(“LogSender”, “ProxyLogSender” + log); String finalLog = Thread.currentThread() + log; mainLogSender.sendLog(finalLog); } }当代理一个新的接口时可见,新的代理类与其他代理类代码是高度相似的,因此可以采用动态代理的方式来完成类似的功能。
3.1 基础用法
与静态代理不同,动态代理类的class是在运行过程中动态生成的。
3.1.1 基础用法
首先定义接口层:
// 定义接口层 interface ILogProcessor { public void printLog(String log); }然后使用Proxy.newProxyInstance完成动态代理如下:
private void main() { ILogProcessor proxy = (ILogProcessor) Proxy.newProxyInstance(this.getClassLoader(), new Class<?>[] {ILogPrinter.class}, new InvocationHandler() {/** • @param proxy 代理对象 • @param method 被调用的方法 • @param args 被调用的方法的参数列表 */ @Override public Object invoke(Object proxy, Method method, Object[] args) { String log = (String)args[0]; Log.d(“LogProcessor”, “ProxyLogProcessor” + log); String finalLog = Thread.currentThread() + log; Log.d(“LogProcessor”, “printLog” + finalLog); return null; } });proxy.printLog(“”); }其中,InvocationHandler就是将静态代理中需要实现的部分抽离了出来,即动态生成的Proxy代理了InvocationHandler。
3.1.2 动态生成的class
动态生成的代理类的方法实际调用都到了InvocationHandler的invoke方法,动态生成的代理类class伪代码如下:
public final class $Proxy0 extends Proxy implements ILogProcessor { static { m3 = Class.forName(“com.bc.sample.ILogProcessor”).getMethod(“printLog”); } private static Method m3; public void printLog(String log) { // 实际调用到了InvocationHandler的invoke方法 super.h.invoke(this, m3, (Object[])log); } }3.1.3 源码分析
下面分析Proxy.newProxyInstance的源码:
public class Proxy implements java.io.Serializable { // 动态生成的class的缓存;ProxyClassFactory可动态生成代理class private static final WeakCache<ClassLoader, Class<?>[], Class<?>> proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());// 生成代理class并返回对应的实例 public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) { Objects.requireNonNull(h); final Class<?>[] intfs = interfaces.clone(); // 查找或动态生成代理类的class Class<?> cl = getProxyClass0(loader, intfs); // 获取动态代理类的构造函数 final Constructor<?> cons = cl.getConstructor(constructorParams); final InvocationHandler ih = h; if (!Modifier.isPublic(cl.getModifiers())) { cons.setAccessible(true); } // 通过反射调用构造函数返回代理类的实例;参数中的InvocationHandler对象作为参数传递给类构造函数; return cons.newInstance(new Object[]{h}); }// 获取动态代理类class private static Class<?> getProxyClass0(ClassLoader loader, Class<?>… interfaces) { return proxyClassCache.get(loader, interfaces); }private static final class ProxyClassFactory implements BiFunction<ClassLoader, Class<?>[], Class<? { // prefix for all proxy class names private static final String proxyClassNamePrefix = “$Proxy”;// WeakCache.get()会调用到apply,最终调用generateProxy生成动态代理类class @Override public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) { // … return generateProxy(proxyName, interfaces, loader, methodsArray, exceptionsArray); } }// 动态生成代理类class private static native Class<?> generateProxy(String name, Class<?>[] interfaces, ClassLoader loader, Method[] methods, Class<?>[][] exceptions); }3.2 Retrofit动态代理
Retrofit是一个开源网络库,其源码中也使用到了动态代理模式。简单介绍如下:
3.2.1 基础用法
首先,新建网络请求对应的接口:
public interface SampleRequestInterface { @HTTP(method = “GET”, path = “/api”, hasBody = true) Call getCall(); }然后,使用Retrofit动态代理生成请求:
public class MainActivity { private void sendRequest() { try { Retrofit retrofit = new Retrofit.Builder() .baseUrl(“http://graph.baidu.com”) .addConverterFactory(GsonConverterFactory.create()) .build();// 返回请求接口的代理类实例,内部实现是用动态代理实现 SampleRequestInterface sampleRequest = retrofit.create(SampleRequestInterface.class); Call call = sampleRequest.getCall(); // 异步发送请求 call.enqueue(new Callback() { @Override public void onResponse(Call call, Response response) { response.body(); }@Override public void onFailure(Call call, Throwable t) {} }); // 同步发送请求 Response response = call.execute(); response.body(); } catch (Exception exception) { exception.printStackTrace(); } } }