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)建立相對應的實例去執行相對應的請求。

相關文章
相關標籤/搜索