基于 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