Retrofit 动态代理源码简析

 

 

引言

在使用Retrofit的时候,我们在通过Builder模式获取到Retrofit对象之后,需要通过create方法来获取到接口对象

public interface Api {
    @GET("api/data/福利/{pageCount}/{pageIndex}")
    Call<BaseModel<ArrayList<Benefit>>> defaultBenefits(
            @Path("pageCount") int pageCount,
            @Path("pageIndex") int pageIndex
    );

    @GET("api/data/福利/{pageCount}/{pageIndex}")
    Observable<BaseModel<ArrayList<Benefit>>> rxBenefits(
            @Path("pageCount") int pageCount,
            @Path("pageIndex") int pageIndex
    );
}
Api api = retrofit.create(Api.class);

如果仔细一看好像不对啊,为什么接口没有实现,就获取到实例了呢?那么retrofit如何实现我们指定接口的实例呢?
其实原理是:动态代理。

初始动态代理

动态代理是代理模式中的一种,动态代理也算是java的一个特色。
Java动态代理类位于Java.lang.reflect包下,一般主要涉及到以下两个类:

  1. Interface InvocationHandler:该接口中仅定义了一个方法Object:invoke(Object obj,Method method,Object[] args)。在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,args为该方法的参数数组。这个抽象方法在代理类中动态实现。

  2. Proxy:该类即为动态代理类。

我们先看一个例子,来对动态代理有一个简单的了解

public interface IAPI {
    @Deprecated
    public void getData(int pageCount, int pageIndex);
}

public static void main(String[] args) {
    IAPI iApi = (IAPI) Proxy.newProxyInstance(IAPI.class.getClassLoader(), new Class<?>[]{IAPI.class}, new InvocationHandler() {
        
        @Override
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            
            Integer pageCount = (Integer) args[0];
            Integer pageIndex = (Integer) args[1];
            System.out.println("参数: " + pageCount + "," + pageIndex);
            System.out.println("方法名: " + method.getName());
            
            Annotation[] annotations = method.getAnnotations();
            System.out.println("注解:" + annotations[0].toString());
            
            return null;
        }
    });
    iApi.getData(5, 8);
}

// 打印结果
参数: 5,8
方法名: getData
注解:@java.lang.Deprecated()

可以看出,我们通过Proxy.newProxyInstance产生的代理类,当调用接口的方法时,都会调用InvocationHandler#invoke方法,在这个方法中可以获取到传入的参数和注解,以及方法名等信息。

同理,retrofit同样可以通过这种动态代理的方法,获取到接口里的注解信息,参数。

Retrofit中的动态代理

Retrofit.create()

通过观察也就很容易理解,retrofit是如何为我们接口生成实例的了。



原文出处  链接:https://www.jianshu.com/p/dcdd286d2e61

猜你喜欢

转载自blog.csdn.net/qq_39792615/article/details/86603584