Retrofit的动态代理

45 篇文章 0 订阅
5 篇文章 0 订阅

Java中的动态代理:
首先动态代理是区别于静态代理的,代理模式中需要代理类和实际执行类(被代理的类)同时实现一个相同的接口,并且在每个接口定义的方法前后都要加入相同的代码,这样有可能很多方法代理类都需要重复。而动态代理就是将这个步骤放入运行时的过程,一个代理类只需要实现InvocationHandler接口中的invoke方法,当需要动态代理时只需要根据接口和一个实现了InvocationHandler的代理对象A生成一个最终的自动生成的代理对象A*。这样最终的代理对象A*无论调用什么方法,都会执行InvocationHandler的代理对象A的invoke函数,你就可以在这个invoke函数中实现真正的代理逻辑。
动态代理的实现机制实际上就是使用Proxy.newProxyInstance函数为动态代理对象A生成一个代理对象A*的类的字节码从而生成具体A*对象过程,这个A*类具有几个特点,一是它需要实现传入的接口,第二就是所有接口的实现中都会调用A的invoke方法,并且传入相应的调用实际方法(即接口中的方法)。

在前面的java动态代理 讲过。

Retrofit中的动态代理
Retrofit中使用了动态代理是不错,但是并不是为了真正的代理才使用的,它只是为了动态代理一个非常重要的功能,就是“拦截”功能。我们知道动态代理中自动生成的A*对象的所有方法执行都会调用实际代理类A中的invoke方法,再由我们在invoke中实现真正代理的逻辑,实际上也就是A*的所有方法都被A对象给拦截了。而Retrofit最重要的是什么?就是把一个网络执行变成像方法调用一样方便的过程:

public interface ZhuanLanApi {
@GET("/api/columns/{user} ")
    Call<ZhuanLanAuthor> getAuthor(@Path("user") String user)
}
再用这个retrofit对象创建一个ZhuanLanApi对象:
ZhuanLanApi api = retrofit.create(ZhuanLanApi.class);
Call<ZhuanLanAuthor>call = api.getAuthor("qinchao");

也就是一个网络调用你只需要在你创建的接口里面通过注解进行设置,然后通过retrofit创建一个api然后调用,就可以自动完成一个Okhttp的Call的创建。通过create的源码的查看:

public<T> T create(final Class<T> service) {
  Utils.validateServiceInterface(service);
  if (validateEagerly) {
     eagerlyValidateMethods(service);
  }
   return (T) Proxy.newProxyInstance(
        service.getClassLoader(),
        new Class<?> [] { service },
        new InvocationHandler() {

            privatefinal Platform platform = Platform.get();

            @Override 
            public Object invoke(Object proxy, Method method, Object... args)throws Throwable {

                if (method.getDeclaringClass() == Object.class) {
                    return method.invoke(this, args);
                }
                if (platform.isDefaultMethod(method)) {
                    return platform.invokeDefaultMethod(method, service, proxy, args);
                }
                ServiceMethod serviceMethod = loadServiceMethod(method);
                OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
                return serviceMethod.callAdapter.adapt(okHttpCall);
            }
    });
}

我们可以看出怎么从接口类创建成一个API对象?就是使用了动态代理中的拦截技术,通过创建一个符合此接口的动态代理对象A*,那A呢?就是这其中创建的这个匿名类了,它在内部实现了invoke函数,这样A*调用的就是A中的invoke函数,也就是被拦截了,实际运行invoke。而invoke就是根据调用的method的注解(前面红色标注的,会传入相应实际函数),从而生成一个符合条件的Okhttp的Call对象,供你使用(调用进行真正网络请求)。

(2)Retrofit实际作用
Retrofit实际上是为了更方便的使用Okhttp,因为Okhttp的使用就是构建一个Call,而构建Call的大部分过程都是相似的,而Retrofit正是利用了代理机制带我们动态的创建Call,而Call的创建信息就来自于你的注解。并且还可以根据配置Adapter等等对网络请求进行相应的处理和改变,这种插件式的解耦方式也提供了很大的扩展性。

可以想象上面的Api接口的类关系图如下:
这里写图片描述
用户定义了一个interface zhuanlanApi,然后retrofit框架利用interface的注解,来自动生成zhuanlanApiImp实现类,因为retrofit框架是基于Okhttp框架的再封装,因此在网络请求的时候okhttp的初始化是可以复用的,只不过请求的时候body,head参数设置不同,而这一部分的不同就是通过用户自定义interface接口注解相关信息来实现的,然后retrofit框架自动完成了动态代理。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值