retrofit的实现原理(二)

转载 2015年07月08日 12:29:27

上篇文章我们已经了解了retrofit的RestAdapter adapter=new RestAdapter.Builder().setEndpoint(url).build()这段代码做了什么.

现在有下面一个接口,

1
2
3
4
interface SimplePOST{
      @POST("/android"
      Response getResponse();
  } 

这篇我们就来了解下 SimplePOST simplePost= adapter.create(SimplePOST.class)的内部逻辑.

1
2
3
4
5
public <T> T create(Class<T> service) {
    Utils.validateServiceClass(service);                                                      
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },   //动态代理
        new RestHandler(getMethodInfoCache(service)));
  }
1
2
3
4
5
6
7
8
static <T> void validateServiceClass(Class<T> service) {      //确保create()参数是一个接口类型,且这个接口没有继承其他的接口.(使用动态代理的前提)
   if (!service.isInterface()) {
     throw new IllegalArgumentException("Only interface endpoint definitions are supported.");
   }
   if (service.getInterfaces().length > 0) {
     throw new IllegalArgumentException("Interface definitions must not extend other interfaces.");
   }
 }

  可以发现adapter.create()方法的内部实现是利用动态代理生成了service接口的一个实现类. 根据动态代理的原理. 可以得知调用实现类的方法其实就是调用InvocationtHandler的对应方法.

这里简单介绍下动态代理.(关于动态代理的原理,可以参考其他博客的文章.)

  委托类:被代理类即称为委托类. 一般不直接调用委托类的方法,而是通过代理类来间接调用.

  假定有委托类A,通过动态代理生成了代理类B,生成的时候需要建立一个InvocationHandler H. 实际我们调用代理类B的方法时,方法内部调用的是H的invoke()方法. 而一般H的invoke方法会调用A的同名方法,这样就实现了代理类B功能.

  虽然这里是运用了动态代理的技术.但是却和一般的动态代理不一样. 一般的动态代理的InvocationHandler应该通过构造函数中传入委托类A.然后在invoke方法中调用A的方法, 但这里是没有委托类的.只是利用动态代理自动生成接口的实现类.

  因为java的动态代理是基于接口的,所以retrofit也要求用户自定义的也必须是一个接口. 

  注意invocationHandler的invoke()方法执行是在我们调用接口的方法的时候执行的.对于上面的代码就simplepost.getResponse()执行的时候.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
private class RestHandler implements InvocationHandler {
   private final Map<Method, RestMethodInfo> methodDetailsCache;
 
   RestHandler(Map<Method, RestMethodInfo> methodDetailsCache) {  //一般的动态代理.InvocationHandler构造函数一般要传入委托类.
     this.methodDetailsCache = methodDetailsCache;
   }
 
   @SuppressWarnings("unchecked"//
   @Override public Object invoke(Object proxy, Method method, final Object[] args)  //动态代理的方法实现.调用委托类的方法,最终会调用invoke方法.
       throws Throwable {
     // If the method is a method from Object then defer to normal invocation.
     if (method.getDeclaringClass() == Object.class) {  //因为接口默认也继承Object.所以接口也有Object中的方法的. 如继承自Object如equals()方法
       return method.invoke(this, args);  //这里需要注意下,这里调用的是invocationHandler(H)的方法.一般的动态代理这里应该是调用委托类(A)的方法.
     }
 
     // Load or create the details cache for the current method.
     final RestMethodInfo methodInfo = getMethodInfo(methodDetailsCache, method);  //把method和RestMethodInfo缓存起来.防止重复解析method.(把方法的注解,返回值,同步异步等信息都解析出来储存在RestMethodInfo中.)
 
     if (methodInfo.isSynchronous) {  //同步的方式.
       try {
         return invokeRequest(requestInterceptor, methodInfo, args);  //核心方法(网络访问).   //可以看到retrofit的synchronous类型方法并不是子线程执行的. 所以在Android平台使用同步方式的retrofit的话要在子线程中.
       catch (RetrofitError error) {
         Throwable newError = errorHandler.handleError(error);
         if (newError == null) {
           throw new IllegalStateException("Error handler returned null for wrapped exception.",  //自定义的ErrorHandler的hanleError()方法不能return null.
               error);
         }
         throw newError;  //注意,同步的方式,当遇到错误的时候,会抛出一个RuntimeException.在Android下尽量不要使用同步的方式(因为RuntimeException是不提示用户主动捕捉的).
       }
     }
 
     if (httpExecutor == null || callbackExecutor == null) {
       throw new IllegalStateException("Asynchronous invocation requires calling setExecutors.");
     }
 
     if (methodInfo.isObservable) {   //rx的方式
       if (rxSupport == null) {
         if (Platform.HAS_RX_JAVA) {
           rxSupport = new RxSupport(httpExecutor, errorHandler, requestInterceptor);
         else {
           throw new IllegalStateException("Observable method found but no RxJava on classpath.");
         }
       }
       return rxSupport.createRequestObservable(new RxSupport.Invoker() {
         @Override public ResponseWrapper invoke(RequestInterceptor requestInterceptor) {
           return (ResponseWrapper) invokeRequest(requestInterceptor, methodInfo, args);
         }
       });
     }
     //同步, Observable方式都不是的话,肯定是异步的方式了.
     // Apply the interceptor synchronously, recording the interception so we can replay it later.
     // This way we still defer argument serialization to the background thread.
     final RequestInterceptorTape interceptorTape = new RequestInterceptorTape();
     requestInterceptor.intercept(interceptorTape);
        
     Callback<?> callback = (Callback<?>) args[args.length - 1];
     httpExecutor.execute(new CallbackRunnable(callback, callbackExecutor, errorHandler) {  //可以看到在Android上异步方式是通过HttpExecutor执行的.是默认子线程执行的. 所以异步方式的retrofit不需要在子线程中执行.
       @Override public ResponseWrapper obtainResponse() {
         return (ResponseWrapper) invokeRequest(interceptorTape, methodInfo, args);
       }
     });
     return null// Asynchronous methods should have return type of void.
   }
 
   /**
    * Execute an HTTP request.
    *
    * @return HTTP response object of specified {@code type} or {@code null}.
    * @throws RetrofitError if any error occurs during the HTTP request.
    */
   private Object invokeRequest(RequestInterceptor requestInterceptor, RestMethodInfo methodInfo,
       Object[] args) {
     String url = null;
     try {
       methodInfo.init(); // Ensure all relevant method information has been loaded.  --->保证method的参数,返回值,注解都解析完成. 可以得到网络访问的url,header,query,访问方式等信息.
 
       String serverUrl = server.getUrl();
       RequestBuilder requestBuilder = new RequestBuilder(serverUrl, methodInfo, converter);
       requestBuilder.setArguments(args);
 
       requestInterceptor.intercept(requestBuilder);  //在网络访问之前,执行拦截器的方法. 保证拦截器是最后起作用的.
 
       Request request = requestBuilder.build();
       url = request.getUrl();
 
       if (!methodInfo.isSynchronous) {
         // If we are executing asynchronously then update the current thread with a useful name.
         int substrEnd = url.indexOf("?", serverUrl.length());
         if (substrEnd == -1) {
           substrEnd = url.length();
         }
         Thread.currentThread().setName(THREAD_PREFIX
             + url.substring(serverUrl.length(), substrEnd));
       }
 
       if (logLevel.log()) {
         // Log the request data.
         request = logAndReplaceRequest("HTTP", request, args);
       }
 
       Object profilerObject = null;
       if (profiler != null) {
         profilerObject = profiler.beforeCall();
       }
 
       long start = System.nanoTime();
       Response response = clientProvider.get().execute(request);  //调用okHttp或者其他Client进行网络访问.并把返回的数据封装进retrofit的Response中.
       long elapsedTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);
 
       int statusCode = response.getStatus();                         //返回码
       if (profiler != null) {
         RequestInformation requestInfo = getRequestInfo(serverUrl, methodInfo, request);
         //noinspection unchecked
         profiler.afterCall(requestInfo, elapsedTime, statusCode, profilerObject);
       }
 
       if (logLevel.log()) {
         // Log the response data.
         response = logAndReplaceResponse(url, response, elapsedTime);
       }
 
       Type type = methodInfo.responseObjectType;
 
       if (statusCode >= 200 && statusCode < 300) { // 2XX == successful request   //返回码在200到300之间认为是一次成功的网络访问.
         // Caller requested the raw Response object directly.
         if (type.equals(Response.class)) {                       //如果方法的返回值类型(封装在responseObjectType)是retrofit的Response的话. 那就不用converter转换.
           if (!methodInfo.isStreaming) {
             // Read the entire stream and replace with one backed by a byte[].
             response = Utils.readBodyToBytesIfNecessary(response);
           }
 
           if (methodInfo.isSynchronous) {  //同步方式
             return response;         
           }
           return new ResponseWrapper(response, response); //异步的时候返回的是这个.
         }
 
         TypedInput body = response.getBody();
         if (body == null) {
           if (methodInfo.isSynchronous) {                   //① 结合下面的② ,返回值类型不同是因为invokeRequest()分别由2个不同的方法调用.  ①是由 invoke()调用的.
             return null;
           }
           return new ResponseWrapper(response, null);       //② 的情况是异步的. 是由callBack模式中的obtainResponse()中调用的.  下面和上面的返回值类型不同的情况皆是如此
         }
 
         ExceptionCatchingTypedInput wrapped = new ExceptionCatchingTypedInput(body);
         try {
           Object convert = converter.fromBody(wrapped, type); //方法的返回值是非Response. 那么由Converter把Response转换成对应的类型.
           logResponseBody(body, convert);
           if (methodInfo.isSynchronous) {
             return convert;
           }
           return new ResponseWrapper(response, convert);
         catch (ConversionException e) {
           // If the underlying input stream threw an exception, propagate that rather than
           // indicating that it was a conversion exception.
           if (wrapped.threwException()) {
             throw wrapped.getThrownException();
           }
 
           // The response body was partially read by the converter. Replace it with null.
           response = Utils.replaceResponseBody(response, null);
 
           throw RetrofitError.conversionError(url, response, converter, type, e);
         }
       }
 
       response = Utils.readBodyToBytesIfNecessary(response);
       throw RetrofitError.httpError(url, response, converter, type);
     catch (RetrofitError e) {
       throw e; // Pass through our own errors.
     catch (IOException e) {
       if (logLevel.log()) {
         logException(e, url);
       }
       throw RetrofitError.networkError(url, e);
     catch (Throwable t) {
       if (logLevel.log()) {
         logException(t, url);
       }
       throw RetrofitError.unexpectedError(url, t);
     finally {
       if (!methodInfo.isSynchronous) {
         Thread.currentThread().setName(IDLE_THREAD_NAME);
       }
     }
   }
 }

对于上面的getMethodInfo()方法, 是把method信息提取出来,封装到RestMethodInfo中. 包括访问方式.Headers,path,参数,返回值等.

1
2
3
4
5
6
7
8
9
10
static RestMethodInfo getMethodInfo(Map<Method, RestMethodInfo> cache, Method method) {
  synchronized (cache) {
    RestMethodInfo methodInfo = cache.get(method);
    if (methodInfo == null) {                  //经典的逻辑,如果缓存中有就从缓存中拿,如果没有,就生成一个新的,并且放到缓存中.
      methodInfo = new RestMethodInfo(method);
      cache.put(method, methodInfo);
    }
    return methodInfo;
  }
}
1
<strong>RestMethodInfo</strong>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
final class RestMethodInfo {
 
 final Method method;
 
  boolean loaded = false;   //方法是否已经load过(解析过)
 
  // Method-level details
  final ResponseType responseType;
  final boolean isSynchronous;      //方法是同步还是异步.
  final boolean isObservable;
  Type responseObjectType;
  RequestType requestType = RequestType.SIMPLE;
  String requestMethod;
  boolean requestHasBody;
  String requestUrl;           
  Set<String> requestUrlParamNames;
  String requestQuery;
  List<retrofit.client.Header> headers;
  String contentTypeHeader;
  boolean isStreaming;
  private enum ResponseType {  //方法的返回值是什么类型
    VOID,                      //void代表没有返回值,-->异步的方式
    OBSERVABLE,               //rxjava
    OBJECT                    //方法的返回值是对象--->同步的方式
  }
  RestMethodInfo(Method method) {
    this.method = method;
    responseType = parseResponseType();
    isSynchronous = (responseType == ResponseType.OBJECT);
    isObservable = (responseType ==           ResponseType.OBSERVABLE);
  }
 
   private ResponseType parseResponseType() {
    // Synchronous methods have a non-void return type.       //同步的方法有一个非void的返回值
    // Observable methods have a return type of Observable.   //Observable的方法 返回值类型应该是Observable
    Type returnType = method.getGenericReturnType();
 
    // Asynchronous methods should have a Callback type as the last argument. //异步的方法最后一个方法的参数类型应该是Callback.
    Type lastArgType = nul
    Class<?> lastArgClass = null;
    Type[] parameterTypes = method.getGenericParameterTypes();
    if (parameterTypes.length > 0) {
      Type typeToCheck = parameterTypes[parameterTypes.length - 1];
      lastArgType = typeToCheck;
      if (typeToCheck instanceof ParameterizedType) {
        typeToCheck = ((ParameterizedType) typeToCheck).getRawType();
      }
      if (typeToCheck instanceof Class) {
        lastArgClass = (Class<?>) typeToCheck;
      }
    }
 
    boolean hasReturnType = returnType != void.class;
    boolean hasCallback = lastArgClass != null && Callback.class.isAssignableFrom(lastArgClass); //如果有CallBack, CallBack只能是最后一个参数.
 
    // Check for invalid configurations.
    if (hasReturnType && hasCallback) {                         //返回值是非void类型和方法有CallBack参数有且只能有一个满足.
      throw methodError("Must have return type or Callback as last argument, not both.");
    }
    if (!hasReturnType && !hasCallback) {
      throw methodError("Must have either a return type or Callback as last argument.");
    }
 
    if (hasReturnType) {
      if (Platform.HAS_RX_JAVA) {
        Class rawReturnType = Types.getRawType(returnType);
        if (RxSupport.isObservable(rawReturnType)) {
          returnType = RxSupport.getObservableType(returnType, rawReturnType);
          responseObjectType = getParameterUpperBound((ParameterizedType) returnType);
          return ResponseType.OBSERVABLE;
        }
      }
      responseObjectType = returnType;
      return ResponseType.OBJECT;
    }
 
    lastArgType = Types.getSupertype(lastArgType, Types.getRawType(lastArgType), Callback.class);
    if (lastArgType instanceof ParameterizedType) {
      responseObjectType = getParameterUpperBound((ParameterizedType) lastArgType);
      return ResponseType.VOID;
    }
 
    throw methodError("Last parameter must be of type Callback<X> or Callback<? super X>.");
  }
 
private void parsePath(String path) {          //解析路径 如GET(string),注意这里会对string进行判断,必须以"/"开头. 所以不能是空字符串,如""
    ...........
}
  List<retrofit.client.Header> parseHeaders(String[] headers) {  //解析Headers注解.
  .....
}
  private void parseParameters() {   //解析方法参数,如方法参数的@Header, @Query等.
  .......
}
  private void parseMethodAnnotations() { //解析http方式.如GET(),POST()
  .......
 }
}

相关文章推荐

WebMatrix进阶教程(1):如何安装和使用微软全新开发工具WebMatrix

WebMatrix使您能够轻松创建网站。您可以从一个开源应用程序(比如WordPress、Joomla、DotNetNuke或Orchard)开始,WebMatrix会为您处理下载、安装和配置这些应用...
  • samtry
  • samtry
  • 2012年06月01日 17:29
  • 1154

教您如何使用WebMatrix创建第一个网页

导读:Microsoft WebMatrix是一个免费的工具,可用于创建、自定义和在Internet上发布网站。 WebMatrix使您能够轻松创建网站。您可以从一个开源应用程序(比如WordP...

Retrofit2.0 ,OkHttp3完美同步持久Cookie实现免登录(二)

通过对Retrofit2.0的基础入门和案例实践,掌握了怎么样使用Retrofit访问网络,加入自定义header,包括加入SSL证书,基本的调试基础,但是正常的开发中会涉及cookie同步问题,可以...

Android Retrofit 实现图文上传(二)

本文转载自 一叶票舟 原文链接:http://blog.csdn.net/jdsjlzx/article/details/52301505 本文已授权微信公众号:鸿洋(hongyangAndr...

Retrofit实现文件上传(二)

1.序言       这几天一直在忙其他乱七八糟的事情,都没能好好敲我的代码呢?昨天,在大力大神的指点下,我对Retrofit的文件上传开悟了;在上节的解析中,我只是蜻蜓点水的提了一下Retrofi...

Retrofit简单原理分析

Retrofit原理分析之前学习了怎么使用Retrofit,现在来学习它的原理。Retrofit使用接口+注解的形式来定义一个网络请求,在通过OkHttp来执行网络请求。现在有很多开源使用了注解Ann...

Retrofit原理分析

Retrofix2原理

Retrofit网络框架的使用以及原理解析

声明:本博客转载自网络,优秀博客值得多次转播。 地址 原文 就目前来说Retrofit2使用的已相当的广泛,那么我们先来了解下两个问题: 1 . 什么是Retrofit? Retrofit是...

Android 网络框架之Retrofit2使用详解及从源码中解析原理

版权声明:本文为博主原创文章,未经博主允许不得转载。 目录(?)[+] 就目前来说Retrofit2使用的已相当的广泛,那么我们先来了解下两个问题: 1 ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:retrofit的实现原理(二)
举报原因:
原因补充:

(最多只允许输入30个字)