Retrofit2 源码解析之动态代理

本文详细解析了Retrofit 2.3.0在Android上的动态代理实现过程,通过示例代码和源码分析,展示了如何生成代理类并理解其工作原理。重点讨论了`Retrofit.create`、`Proxy.newProxyInstance`等关键步骤,揭示了动态代理在内存中生成字节码的过程。
摘要由CSDN通过智能技术生成

基于 Retrofit 2.3.0 & Android 8.1 分析 Java 动态代理在 Android 上的实现
本文为博主原创文章,未经允许不得转载
推荐阅读另一篇博文:《Handler 源码解析》

动态代理最难理解的就是动在何处,其实动就动在代理类是完全在内存中生成的,包括创建类字节码、加载、链接、初始化代理类对象整个过程。不同于那些在编译期就生成 Xxx.class 的对象,那是磁盘文件,是人眼可见的,动态代理类的的字节码仅存在于内存中,是看不见的。本文主要介绍代理类的生成过程,看完本文应该可以彻底理解动态代理。

Retrofit 使用示例

public interface XinZhiWeatherApi {
    @GET("{type}?key=xxxxxxxxxx&&language=zh-Hans&unit=c")
    Flowable<WeatherBean> getNowWeather(@Path("type") String type, @Query("location") String location);
}

public static XinZhiWeatherApi initWeatherApi() {
    HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
    interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
    OkHttpClient client = new OkHttpClient.Builder()
            .addInterceptor(interceptor)
            .retryOnConnectionFailure(true)
            .connectTimeout(10, TimeUnit.SECONDS)
            .build();

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(BASE_URL)
            .client(client)
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .addConverterFactory(GsonConverterFactory.create())
            .build();
    return retrofit.create(XinZhiWeatherApi.class);
}

如上所示,Retrofit 的使用非常简单。本文只关注 retrofit.create()

Retrofit.create

Retrofit.java

  public <T> T create(final Class<T> service) {
    // 必须是接口类型且不能继承其它接口,否则抛出异常
    Utils.validateServiceInterface(service);
    // validateEagerly 默认是 false
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    // 返回动态生成的代理类
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
        new InvocationHandler() {
          private final Platform platform = Platform.get();

          @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
              throws Throwable {
            // If the method is a method from Object then defer to normal invocation.
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }

我们看到,Retrofit 的动态代理使用比较简单,不涉及接口的实现类,只有一个匿名的 InvocationHandler 类。下面写个示例代码(使用 IntelliJ IDEA 编写):

public interface ISubject {
    void sayHello();
}

public static void main(String[] args) {
    ISubject subject = (ISubject) Proxy.newProxyInstance(Main.class.getClassLoader(), new Class[]{ISubject.class},
        new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    System.out.println("InvocationHandler$invoke: call " + method.getName());
                    return 0;
                }
            });

    System.out.println("class of subject: " + subject.getClass().getName());
    System.out.println("super class of subject: " + sub
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值