博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
retrofit的实现原理(二)
阅读量:5082 次
发布时间:2019-06-13

本文共 14034 字,大约阅读时间需要 46 分钟。

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

现在有下面一个接口,

  interface SimplePOST{		@POST("/android")  		Response getResponse();	} 

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

public 
T create(Class
service) { Utils.validateServiceClass(service); return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class
[] { service }, //动态代理 new RestHandler(getMethodInfoCache(service))); }
static 
void validateServiceClass(Class
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()执行的时候.

private class RestHandler implements InvocationHandler {    private final Map
methodDetailsCache; RestHandler(Map
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,参数,返回值等.

static RestMethodInfo getMethodInfo(Map
cache, Method method) { synchronized (cache) { RestMethodInfo methodInfo = cache.get(method); if (methodInfo == null) { //经典的逻辑,如果缓存中有就从缓存中拿,如果没有,就生成一个新的,并且放到缓存中. methodInfo = new RestMethodInfo(method); cache.put(method, methodInfo); } return methodInfo; } }
RestMethodInfo
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
requestUrlParamNames; String requestQuery; List
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
or Callback
."); }private void parsePath(String path) { //解析路径 如GET(string),注意这里会对string进行判断,必须以"/"开头. 所以不能是空字符串,如"" ...........} List
parseHeaders(String[] headers) { //解析Headers注解.  .....} private void parseParameters() { //解析方法参数,如方法参数的@Header, @Query等.  .......} private void parseMethodAnnotations() { //解析http方式.如GET(),POST()  ....... }}

  

转载于:https://www.cnblogs.com/laiqurufeng/p/4497758.html

你可能感兴趣的文章
关于ExecuteNonQuery执行的返回值(SQL语句、存储过程)
查看>>
UVa540 Team Queue(队列queue)
查看>>
mysql数据增删改查
查看>>
shell中下载最新版本或指定版本的办法(Dockerfile 中通用)
查看>>
极客时间-左耳听风-程序员攻略-分布式架构工程设计
查看>>
akka之种子节点
查看>>
不知道做什么时
查看>>
matlab 给某一列乘上一个系数
查看>>
密码学笔记——培根密码
查看>>
Screening technology proved cost effective deal
查看>>
MAC 上升级python为最新版本
查看>>
创业老板不能犯的十种错误
查看>>
Animations介绍及实例
查看>>
判断请求是否为ajax请求
查看>>
【POJ2699】The Maximum Number of Strong Kings(网络流)
查看>>
spring boot配置跨域
查看>>
BZOJ 1996 合唱队(DP)
查看>>
进击吧!阶乘——大数乘法
查看>>
安卓学习资料推荐-25
查看>>
Mysql数据库备份和还原常用的命令
查看>>