Retrofit使用动态代理来生成api的类和实例,开发过程中却无感知,下面是一个最朴素的使用方式:
- 初始化retrofit
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://" + server.getHostName() + ":" + server.getPort())
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient.build())
.build();
- 定义接口
public interface Api {
@GET("/")
@Headers("Content-Type:application/json")
Call<JsonResPonse> getMethodJsonResp(@Query("id") String id);
}
- 创建api
Api api = retrofit.create(Api.class);
- 发请请求:
JsonResPonse fromJson = api.getMethodJsonResp("1").execute().body();
用户只是写了一个请求接口Api,以及定义了一些方法。可以猜测的是在调用create的时候,生成相应的类,以及实例,在调用方法的时候,会对请求,返回,以及注解进行处理。
只要找到生成的类,再反编译便一目了然。
如何获得动态代理生成的类
自定义的Api接口,为了方便观察,这里只使用了一个方法:
public interface Api {
@GET("/")
@Headers("Content-Type:application/json")
Call<JsonResPonse> getMethodJsonResp(@Query("id") String id);
}
在api创建之前加入这段代码,用来保存生成的class文件用:
Properties properties = System.getProperties();
properties.put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
运行后,生成的class文件保存在com.sun.proxy文件夹下面,文件是以$Proxy+数字命名.用as打开后:
public final class $Proxy0 extends Proxy implements Api {
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final Call getMethodJsonResp(String var1) throws {
try {
return (Call)super.h.invoke(this, m3, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("com.tcl.component.portal.Api").getMethod("getMethodJsonResp", Class.forName("java.lang.String"));
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
可见当调用getMethodJsonResp时会调用:
return (Call)super.h.invoke(this, m3, new Object[]{var1});
super.h便是InvocationHandler,在retrofit creat方法中实现:
new InvocationHandler() {
private final Platform platform = Platform.get();
private final Object[] emptyArgs = new Object[0];
@Override public @Nullable 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);
}
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
}
});
可见处理顺序为: