retrofit源码中的动态代理

一、retrofit简介java

retrofit从诞生开始,就把其余的网络请求库给pk下去了,例如之前用了好多年的volley。他是一个优秀的网络请求框架而不是一个网络库,他须要结合okhttp来使用。 retrofit最大的特色,在于能够用一个javainterface经过注解去表示一个http请求。api

(1)定义GET请求的interfacebash

@POST(IMAGE_URL + "/api/getUrl")
    Observable<ResponseEntity>>> getUrl(@Body CommonloadEntity params);

复制代码

(2)经过retrofit建立service实例:网络

Retrofit retrofit = new Retrofit.Builder()
.baseUrl("url")
.build();
复制代码

(3)获取call实例执行http请求,这个地方执行的是okhttp内部的网络请求。框架

官方介绍他的特色的:能够用一个java interface经过注解去表示一个http请求。ide

二、动态代理机制post

retrofit中一个很是重要的机制在于他的动态代理机制。经过上面第二步能够看出来:retrofit将一个java interfac转化为一个能够进行http请求的对象。ui

什么是动态代理机制?经过下面一个例子来了解下:url

先定义一个java interfacespa

interface Game {
    fun play(text:String)
}
复制代码

一个interface是不能够直接建立一个对象的,因此动态代理所作的是在运行时生成一个实现了该interface的类的class对象。proxy的getProxyClass的方法注释:

Returns the {@code java.lang.Class} object for a proxy class given a class loader and an array of interfaces. The proxy class will be defined by the specified class loader and will implement all of the supplied interfaces. If any of the given interfaces is non-public, the proxy class will be non-public. If a proxy class for the same permutation of interfaces has already been defined by the class loader, then the existing proxy class will be returned; otherwise,a proxy class for those interfaces will be generated dynamically and defined by the class loader.

字面上的意思就是说,在运行时生成一个代理class二进制流,并经过传入的classLoader去加载成一个代理class对象,该class实现了传入的第二个参数对应的interface。

三、经过反射建立具体实例

val game = Proxy.getProxyClass(Game::class.java.classLoader,Game::class.java)

        val construct = game.getConstructor(InvocationHandler::class.java)
        var gameProxy = construct.newInstance(object :InvocationHandler{
            override fun invoke(proxy: Any?, method: Method?, args: Array<out Any>?): Any {
                return "i am proxy"
            }

        })
复制代码

动态代理有什么做用?结合《深刻理解java虚拟机》一书中的答案:动态代理中所谓的动态,是针对使用java代码编写了代理类的静态代理而言的,它的优点不在于省去了编写代理类那一点工做量,而是实现了能够在原始类和接口还未知的时候,就肯定代理类的代理行为,当代理类与原始类脱离直接联系后,就能够很灵活地重用与不一样的应用场景之中。结合 retrofit来说,就是在具体的http请求还未知的状况下,就肯定了http的请求代码。

四、retrofit中的动态代理

上面的例子中,在执行建立service的时候

RetrofitService service = retrofit.create(RetrofitService.class);
复制代码

这一句,虚拟机内部生成了代理类的Class二进制流,并加载到虚拟机中造成代理的class对象,再反射获得代理类对象,而该代理类实现了RetrofitService,并持有了Invocationhandler 的引用。 当调用里面的方法获取到具体的call的时候,就会调用invocationHandler引用的对象的invoke方法,而且传入RetrofitService的method对象。

InvocationHandler引用的对象的invoke方法会经过该method对象,获得方法的注解以及参数,获得http请求的连接、请求方法、请求路径、参数等请求信息,构建一个okhttp的请求并执行。

五、如何实现本身的Retrofit

(1)建立一个注解

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface HttpProxy {
    String get();
    String post();
}

复制代码

(2)建立一个回调类

public interface Call<T> {
    void enqueue(CallBack<T> callBack);
}

复制代码

(3)请求的回调接口

public interface CallBack<T> {
    void onResponse(T result);
    void onFailure();
}

复制代码

(4)建立接口

public interface GetService {
    @HttpProxy("hello")
    Call<String> hello();
}
复制代码

(5)建立相对应的实例去执行相对应的请求。

相关文章
相关标签/搜索