Retrofit的动态代理
都知道Retrofit
是通过动态代理来生成代理对象作为网络请求的发起者。
今天就来看下动态代理是怎么操作的。或者说是怎么让一个貌似接口的对象调用它的抽象方法呢?
先来看代码
public static void main(String[] args) {Factory factory = new Factory();Bird bird = factory.create(Bird.class);bird.fly();
}interface Bird {void fly();
}复制代码
这里代码通过一个Factory
实例调用create
方法,传入一个接口的class
对象就可以返回一个接口的实例,可以调用接口中的方法fly()
。
而在我们的静态代码中并没有一个类去实现了这个Bird
接口(完整代码可以看下方)。那么这个对象到底是从哪里来的呢?
完整代码如下
public class DynamicProxy {interface Bird {void fly();}public static void main(String[] args) {Factory factory = new Factory();Bird bird = factory.create(Bird.class);bird.fly();}static class Factory implements InvocationHandler {public <T> T create(Class<T> target) {return (T) Proxy.newProxyInstance(target.getClassLoader(),new Class[]{target},this);}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("flying...");return null;}}
}
复制代码
在调用bird.fly()
时,输出结果为flying...
,很明显,代码中就如同开始所说的,并不存在一个实现了Bird
接口的子类,而bird
又实实在在调用了fly()
方法。唯一的可能就是bird
是接口的实例(或者说实现接口的子类的对象)。这里看起来似乎就有些诡异了。
当然编程没有魔法,这里只是利用到了Java
的动态代理,通过Proxy.newProxyInstance()
方法生成实现了指定接口的子类,然后返回了这个动态生成类的实例对象。
这个子类在调用接口中的方法时,其实调用的是InvocationHandler
的invoke()
方法。在此方法中会有对应参数的回调,可以根据这些参数做出合适的拦截/增强等操作。
要留意的一点是JDK
提供的动态代理,动态生成的子类是继承自Proxy
类的,,而Java
是不支持多继承的,所以很显然。通过动态代理返回的对象必然是以接口形式来接收的,扩展的只有接口和实现接口的子类,对于一些没有实现接口的类是没有办法进行扩展的。(cglib
支持扩展类)
知道了这些也就明白了Retrofit
的动态代理大致是个什么逻辑。
下面仿造Retrofit
通过方法上注解来模拟一次网络请求吧。
通过在接口中在方法上的注解,确定一些请求的参数。然后创建代理对象,在方法中拼接处完整的Url
, https://github.com/search?q=java
请求网络,并且在响应头中的Status
字段打印出来。
public interface Bird {@Protocol()@Method()@Path("search")@Query("q=java")@Url("github.com")String fly();
}public class Test {public static void main(String[] args) {Factory factory = new Factory();Bird bird = factory.create(Bird.class);String status = bird.fly();System.out.println(status);//输出 Status: 200 OK}
}
复制代码
部分代码
public class Factory implements InvocationHandler {OkHttpClient httpClient = new OkHttpClient();public <T> T create(Class<T> target) {return (T) Proxy.newProxyInstance(target.getClassLoader(),new Class[]{target},this);}public Object invoke(Object proxy, java.lang.reflect.Method method, Object[] args) throws Throwable {String get = method.getAnnotation(Method.class).method();String protocol = method.getAnnotation(Protocol.class).value();String url = method.getAnnotation(Url.class).value();String path = method.getAnnotation(Path.class).value();String query = method.getAnnotation(Query.class).value();String entire_url = protocol + "://" + url + "/" + path + "?" + query;System.out.println(entire_url);Request build = new Request.Builder().url(entire_url).get().build();return httpClient.newCall(build).execute().headers().get("Status");}
}
复制代码
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Method {String method() default "GET";
}@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Url {String value();
}@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Protocol {String value() default "https";
}@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Path {String value();
}@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Query {String value() default "";
}复制代码
转载于:https://juejin.im/post/5a31ee51f265da430e4f2bea
Retrofit的动态代理相关推荐
- [动态代理三部曲:下] - 从动态代理,看Retrofit的源码实现
前言 关于动态代理的系列文章,到此便进入了最后的"一出好戏".前俩篇内容分别展开了:从源码上,了解JDK实现动态代理的原理:以及从动态代理切入,学会看class文件结构的含义. 如 ...
- Retrofit2 源码解析之动态代理
基于 Retrofit 2.3.0 & Android 8.1 分析 Java 动态代理在 Android 上的实现 未经允许不得转载 Retrofit 使用示例 public interfa ...
- [动态代理三部曲:上] - 动态代理是如何坑掉了我4500块钱
前言 不知道,起这个名字算不算是标题党呢?不过如果小伙伴们可以耐心看下去,因为会觉得不算标题党~ 这是一个系列文章,目的在于通过动态代理这个很基础的技术,进而深入挖掘诸如:动态生成class:Clas ...
- java 获取动态的service_【Android】动态代理在 Retrofit 中的使用
首先,什么是动态代理和为什么会有动态代理. 众所周知,Java 是一门静态语言,编写完的类,无法在运行时做动态修改. 一个简单的动态代理如下: 1.先定义一个接口,想要使用动态代理,必须先定义一个接口 ...
- Android代理模式(静态代理,动态代理,Retrofit代理模式分析)
文章目录 代理模式 前言:AOP编程(面向切面编程) 一. 代理思想 1. 静态代理 2. 动态代理 3. 动态代理的实现 二. Retrofit代理模式分析 代理模式 前言:AOP编程(面向切面编程 ...
- Android开发中无处不在的设计模式——动态代理模式
继续更新设计模式系列.写这个模式的主要原因是近期看到了动态代理的代码. 先来回想一下前5个模式: - Android开发中无处不在的设计模式--单例模式 - Android开发中无处不在的设计模式-- ...
- android中多态的应用_动态代理原理及在 Android 中的应用
code小生 一个专注大前端领域的技术平台公众号回复Android加入安卓技术群 作者:trampcr 链接:https://www.jianshu.com/p/492903ab2fae 声明:本文已 ...
- 动态代理[JDK]机制解析
代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问.代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理. 动态代理是一种比较常用的代理 ...
- Android APP热更新中的插件化(Hook技术:反射或动态代理),Demo (2)
修改AAPT,资源分区,用于Android插件化- https://github.com/BaoBaoJianqiang/AAPT -- Android下的挂钩(hook)和代码注入(inject) ...
最新文章
- 题目 1083:【蓝桥杯】【入门题】Hello, world!
- reactor官方文档译文(2)Reactor-core模块
- InfoWorld的日志管理系统评测
- leetcode 501. 二叉搜索树中的众数(Java版)
- 关于ECMAScript6 的学习01-ES6 的六种变量声明方式===关于常量const
- OpenShift 之 Quarkus(1)创建第一个Quarkus应用
- Linux离线同步时间
- 谈谈现在软件测试行业的趋势和面试必备的东西
- watch the fixed address in qt
- win10+cuda10+tensorflow-gpu最新安装教程
- php webshell 过狗
- python sqrt(4)*sqrt(9),Python sqrt() 函数
- 数字化给财税行业带来的星星之火
- python程序设计心得体会感想-如何快速学会Python
- Docker buil提示https://registry-1.docker.io/v2/: read tcp 10.221->:443: read: connection reset by peer
- 先试后买!解析购物新体验背后的移动AI+AR技术
- 【操作系统】第2章 进程与线程
- 技术状态管理(六)-技术状态审核
- oracle 菜单不见了,开始菜单不见了怎么办 开始菜单不见了解决方法【详解】
- java 如何建立servlet_Servlet怎么新建
热门文章
- 常见硬件术语大全(上)
- 数据库高可用架构(MySQL、Oracle、MongoDB、Redis)
- ●洛谷P3168 [CQOI2015]任务查询系统
- [codevs1022]覆盖
- codevs 1227 方格取数 2
- [LeetCode]Gray Code
- Ubuntu 11.10 开机让 Varnish 跟随 Nginx 一起启动
- [转]Visual Assist X设置
- 如何向列表中添加数据值(管理员篇)
- NameError: name 'go' is not defined