美文网首页
Android代理模式基础讲解

Android代理模式基础讲解

作者: android不是安卓 | 来源:发表于2022-04-15 16:32 被阅读0次

一、代理模式

代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问。

二、静态代理

静态代理的代理类持有被代理者的引用,在方法调用时,代理对象调用了被代理对象去执行真正的实现。

2.1 简单示例
假如对于一个日志处理功能,可通过代理类代理实例日志处理类:

// 1.首先定义接口层
interface ILogProcessor {
    public void printLog(String log);
}

// 2.定义实现类
public class MainLogProcessor implements ILogProcessor {

    @Override
    public void printLog(String log) {
        Log.d("LogProcessor", "MainLogProcessor" + log);
    }
}

// 3.定义代理类
public class LogProcessorProxy implements ILogProcessor {
    // 代理类持有被代理类的引用
    private ILogPrinter mainLogProcessor = new MainLogProcessor();

    @Override
    public void printLog(String log) {
     // 代理类需要完成的一些额外处理
        Log.d("LogProcessor", "ProxyLogProcessor" + log);
        String finalLog = Thread.currentThread() + log;
        mainLogPrinter.printLog(finalLog);
    }
}

这样,在使用过程中,可以按如下方式使用:

public void main() {
 String log = "important log";
 ILogPrinter proxy = new LogPrinterProxy();
 proxy.printLog(log);
}

2.2 AIDL
AIDL中也用到了代理模式,在Android Studio中新建一个AIDL文件,如下所示:

// IMyAidlInterface.aidl
package com.bc.sample;

interface IMyAidlInterface {
    void testFun();
}

在点击make project后,会自动生成AIDL接口对应的代码,即对应的Stub和Proxy,可以看到AIDL的Proxy是通过静态代理实现,自动生成的代码如下所示:

package com.bc.sample;
// Declare any non-default types here with import statements

public interface IMyAidlInterface extends android.os.IInterface
{
  /** Default implementation for IMyAidlInterface. */
  public static class Default implements com.bc.sample.IMyAidlInterface
  {
    @Override public void testFun() throws android.os.RemoteException
    {
    }
    @Override
    public android.os.IBinder asBinder() {
      return null;
    }
  }
  /** Local-side IPC implementation stub class. */
  public static abstract class Stub extends android.os.Binder implements com.bc.sample.IMyAidlInterface
  {
    private static final java.lang.String DESCRIPTOR = "com.bc.sample.IMyAidlInterface";
    /** Construct the stub at attach it to the interface. */
    public Stub()
    {
      this.attachInterface(this, DESCRIPTOR);
    }
    /**
     * Cast an IBinder object into an com.bc.sample.IMyAidlInterface interface,
     * generating a proxy if needed.
     */
    public static com.bc.sample.IMyAidlInterface asInterface(android.os.IBinder obj)
    {
      if ((obj==null)) {
        return null;
      }
      android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
      if (((iin!=null)&&(iin instanceof com.bc.sample.IMyAidlInterface))) {
        return ((com.bc.sample.IMyAidlInterface)iin);
      }
      return new com.bc.sample.IMyAidlInterface.Stub.Proxy(obj);
    }
    @Override public android.os.IBinder asBinder()
    {
      return this;
    }
    @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
    {
      java.lang.String descriptor = DESCRIPTOR;
      switch (code)
      {
        case INTERFACE_TRANSACTION:
        {
          reply.writeString(descriptor);
          return true;
        }
        case TRANSACTION_testFun:
        {
          data.enforceInterface(descriptor);
          this.testFun();
          reply.writeNoException();
          return true;
        }
        default:
        {
          return super.onTransact(code, data, reply, flags);
        }
      }
    }

 // 主要关注代理模式的实现;可以看到AIDL的Proxy是通过静态代理模式实现
    private static class Proxy implements com.bc.sample.IMyAidlInterface
    {
      private android.os.IBinder mRemote;
      Proxy(android.os.IBinder remote)
      {
        mRemote = remote;
      }
      @Override public android.os.IBinder asBinder()
      {
        return mRemote;
      }
      public java.lang.String getInterfaceDescriptor()
      {
        return DESCRIPTOR;
      }
      @Override public void testFun() throws android.os.RemoteException
      {
        android.os.Parcel _data = android.os.Parcel.obtain();
        android.os.Parcel _reply = android.os.Parcel.obtain();
        try {
          _data.writeInterfaceToken(DESCRIPTOR);
          boolean _status = mRemote.transact(Stub.TRANSACTION_testFun, _data, _reply, 0);
          if (!_status && getDefaultImpl() != null) {
            getDefaultImpl().testFun();
            return;
          }
          _reply.readException();
        }
        finally {
          _reply.recycle();
          _data.recycle();
        }
      }
      public static com.bc.sample.IMyAidlInterface sDefaultImpl;
    }
    static final int TRANSACTION_testFun = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    public static boolean setDefaultImpl(com.bc.sample.IMyAidlInterface impl) {
      // Only one user of this interface can use this function
      // at a time. This is a heuristic to detect if two different
      // users in the same process use this function.
      if (Stub.Proxy.sDefaultImpl != null) {
        throw new IllegalStateException("setDefaultImpl() called twice");
      }
      if (impl != null) {
        Stub.Proxy.sDefaultImpl = impl;
        return true;
      }
      return false;
    }
    public static com.bc.sample.IMyAidlInterface getDefaultImpl() {
      return Stub.Proxy.sDefaultImpl;
    }
  }
  public void testFun() throws android.os.RemoteException;
}

三、动态代理

在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<BaseResponse> 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<BaseResponse> call = sampleRequest.getCall();
            // 异步发送请求
            call.enqueue(new Callback<BaseResponse>() {
                @Override
                public void onResponse(Call call, Response response) {
                    response.body();
                }

                @Override
                public void onFailure(Call call, Throwable t) {

                }
            });
            // 同步发送请求
            Response<BaseResponse> response = call.execute();
            response.body();
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }
}

3.2.2 Retrofit动态代理实现
接下来分析Retrofit内部是如何使用动态代理模式的:

public final class Retrofit {
 
 public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
        new InvocationHandler() {
          private final Platform platform = Platform.get();

          @Override public Object invoke(Object proxy, Method method, Object... args)
              throws Throwable {
            // ...
            // 真正需要执行的代码
            ServiceMethod serviceMethod = loadServiceMethod(method);
            OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }
}

相关文章

网友评论

      本文标题:Android代理模式基础讲解

      本文链接:https://www.haomeiwen.com/subject/vpkqertx.html