retrofit的实现原理(二)

上篇文章我们已经了解了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()
  .......
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值