Retrofit的设计模式 -- 动态代理模式

Retrofit的设计模式 -- 动态代理模式

96 gzfgeh 关注

2017.03.03 10:14* 字数 412 阅读 63评论 0喜欢 3

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

没有代理对象传过去,但是运用的动态代理的特性拿到了接口中的任何参数,用来实现自己后的事情.

猜你喜欢

转载自blog.csdn.net/xinzhou201/article/details/81240196