美文网首页
Retrofit的设计模式 -- 动态代理模式

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

作者: gzfgeh | 来源:发表于2017-03-03 10:14 被阅读158次

    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
    

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

    相关文章

      网友评论

          本文标题:Retrofit的设计模式 -- 动态代理模式

          本文链接:https://www.haomeiwen.com/subject/jvslgttx.html