Retrofit中的动态代理模式
最近有时间开始了看源码的节奏,看了Retrofit源码上来就看到了动态代理模式,但是严格来说不算是真正的动态代理模式,就是这样才是真正大牛的代码,随机应变,不受固定模式影响.
1、正规的动态代理模式
/**
* Description:代理接口
*/
public interface RetrofitInterface {
String retrofitInterfaceFunc(String s);
}
/**
* Description:被代理类
*/
public class Retrofit implements RetrofitInterface {
@Override
public String retrofitInterfaceFunc(String s) {
System.out.printf("progress " + s + "\n");
return s;
}
}
/**
* Description: 代理类
*/
public class RetrofitProxy {
private Retrofit retrofit;
public RetrofitProxy(Retrofit retrofit) {
this.retrofit = retrofit;
}
public <T> T create(Class<T> service){
if (!service.isInterface()){
throw new IllegalArgumentException("API declarations must be interfaces. ");
}
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class[]{service},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before\n");
method.invoke(retrofit, args);
// System.out.printf("function name: " + method.getName() + "\n");
// System.out.printf("function return type: " + method.getReturnType().getName() + "\n");
// System.out.printf("args name: " + args[0].toString() + "\n");
System.out.printf("after \n");
return null;
}
});
}
}
/**
* Description:客户端
*/
public class TestMain {
public static void main(String[] args) {
RetrofitProxy proxy = new RetrofitProxy(new Retrofit());
RetrofitInterface retrofitInterface = proxy.create(RetrofitInterface.class);
retrofitInterface.retrofitInterfaceFunc("12345");
}
}
打印结果如下:
before
progress 12345
after
Process finished with exit code 0
这些网上多的很,贴出来主要是和Retrofit中的动态代理有个对比.
2、Retrofit中的动态代理
首先我们用的时候,先写调用接口
public interface RetrofitService {
@Headers({"Content-type:application/json;charset=UTF-8"})
@GET("data/{type}/20/{page}")
Observable<BaseBean<List<ResultBean>>> getNewsList(@Path("type") String type, @Path("page") int page);
}
现在问题来了,我们在后面的代码中没有真正实现过这个接口啊,Retrofit如何动态代理的,我们后面用到的这个Interface就是这样的
retrofit.create(RetrofitService.class);
我们跟进去看
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() {
private final Platform platform = Platform.get();
@Override public Object invoke(Object proxy, Method method, 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 serviceMethod = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
真正起作用的是
ServiceMethod serviceMethod = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
但是我们根本没有看到method.invoke字眼(前面的不是,只是一些容错判断), 其实这里可以想到了Retrofit根本没有实现正规的动态代理,因为咱们没有传要代理的对象进来,他这样写就是为了用动态代理的特性来拿到自己想要的数据,然后根据他的想法(享元模式建立请求),我们可以把前面的Demo改成Retrofit类似的情况
3、模仿Retrofit改造后的Demo
/**
* Description: 代理类
*/
public class RetrofitProxy {
// private Retrofit retrofit;
//
// public RetrofitProxy(Retrofit retrofit) {
// this.retrofit = retrofit;
// }
public static <T> T create(Class<T> service){
if (!service.isInterface()){
throw new IllegalArgumentException("API declarations must be interfaces. ");
}
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class[]{service},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before\n");
// method.invoke(retrofit, args);
System.out.printf("function name: " + method.getName() + "\n");
System.out.printf("function return type: " + method.getReturnType().getName() + "\n");
System.out.printf("args name: " + args[0].toString() + "\n");
System.out.printf("after \n");
return null;
}
});
}
}
/**
* Description:客户端
*/
public class TestMain {
public static void main(String[] args) {
// RetrofitProxy proxy = new RetrofitProxy(new Retrofit());
RetrofitInterface retrofitInterface = RetrofitProxy.create(RetrofitInterface.class);
retrofitInterface.retrofitInterfaceFunc("12345");
}
}
运行结果如下:
before
function name: retrofitInterfaceFunc
function return type: java.lang.String
args name: 12345
after
Process finished with exit code 0
没有代理对象传过去,但是运用的动态代理的特性拿到了接口中的任何参数,用来实现自己后的事情.
网友评论