Android Retrofit 2实现原理分析

1.Retrofit的原理是什么

Retrofit是一个基于AOP思想,对RestfulApi注解进行动态代理的网络框架。


2.AOP是什么

Aspect Oriented Programming  面向切面编程。

面向切片编程是编程实践中的解耦利器,能够极大的减少对象的创建,


AOP的思想是在不影响主体逻辑的前提下,动态的插入逻辑,利用反射进行调用。在执行频度不是很高的前提下,很多辅助代码都可以采用这种方式实现。


3.动态代理

以往我们实现代理的方式是定义一个接口,写一个真实实现类和一个代理类,这种方法我们称之为静态代理。这种方式的弊端是,当有很多类需要代理时,需要实现多个代理类。

而利用AOP,我们可以将代理实现的很优雅,只需要一个代理类就可以。这种方式我们称之为动态代理。

public interface IWork {

    void doWork();

}
定义接口


public class Coder implements IWork {

    @Override
    public void doWork() {
        Log.i("AOP", "码农写代码");
    }
}

public class Student implements IWork {
    @Override
    public void doWork() {
        Log.i("AOP","学生学习");
    }
}
实现接口

public class DynamicProxy implements InvocationHandler {

    //代理类
    private Object target;

    /**
     * 绑定委托对象并返回一个代理类
     * @param target
     * @return
     */
    public Object bind(Object target) {
        this.target = target;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }

    /**
     * @param proxy 被代理的对象。
     * @param method:要调用的方法
     * @param args:方法调用时所需要的参数
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = null;
        // 切面插入前
        Log.i("AOP","代理逻辑插入前");
        // 执行真实类逻辑
        result = method.invoke(target, args);
        // 切面插入后
        Log.i("AOP","代理逻辑插入后");
        return result;
    }

}
代理类

        IWork iWork = (IWork) new DynamicProxy().bind(new Coder());
        iWork.doWork();

        iWork = (IWork) new DynamicProxy().bind(new Student());
        iWork.doWork();
代码应用

一个代理类同时代理了Coder和Student两个实体类。


说了这么多,回归正题。

Retrofit就是利用这种动态代理的方式实现的,下面我们看源码。

public interface RetrofitAPI {


    @Headers({"Accept:application/x.vr.v1.0.1+json"})
    @POST("rest/find")
    @FormUrlEncoded
    Call<AppListEntity> getAppList(@Header("Authorization") String token, @FieldMap Map<String, Object> map);
}
定义接口

RetrofitAPI api = retrofit.create(RetrofitAPI.class);
接口代理实现


 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 {
            // If the method is a method from Object then defer to normal invocation.
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            ServiceMethod serviceMethod = loadServiceMethod(method);
            OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }
Retrofit create方法利用泛型实现了动态代理


ServiceMethod loadServiceMethod(Method method) {
    ServiceMethod result;
    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
        result = new ServiceMethod.Builder(this, method).build();
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

这个方法用来解析Retrofit的注解,生成相应的method方法

            OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);
最终被OkHttp调用。


有兴趣的可以研究一下Retrofit的注解是如何解析的。


参考文章

感谢yanbin对AOP的讲解

http://www.cnblogs.com/yanbincn/archive/2012/06/01/2530377.html















版权声明:本文为jasonwang18原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。