Retrofit从基本使用到源码学习
A type-safe HTTP client for Android and Java
正如官方所说,Retrofit是一个在Android和Java上使用的类型安全的Http客户端。底层网络请求依赖okHttp。
Retrofit 到底解决了什么问题???
首先我们直接用OkHttp请求网络时,手下要封装一个网络请求的类,然后请求参数和URL都需要手动拼接。
- 使用注解简化了URL拼装,公共参数参数传递的代码。
- 使用反射+动态代理 生成接口访问类,省去了自己实现和初始化接口方法调用的麻烦。
- 通过适配器简化了请求和响应数据的转换。
- 通过和RxJava结合简化了线程切换过程。
一 基本使用
1 引入依赖
implementation 'com.squareup.retrofit2:retrofit:2.0.2'
implementation 'com.squareup.retrofit2:converter-gson:2.0.2'
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.squareup.retrofit2:adapter-rxjava:2.0.2'
retrofit 是核心组件
converter-gson 是转换器
2 定义接口
public interface GitHub {
@GET("/repos/{owner}/{repo}/contributors")
Call<List<Contributor>> contributors(
@Path("owner") String owner,
@Path("repo") String repo);
}
其中的接口方法对应,后台服务的一个接口。上的demo是使用的GET请求,注解的参数是请求对应的路径;listRepos方法需要传入一个String类型参数,通过@Path("user")
可以标记该参数要填充到请求路径中的哪个变量,可以动态生成URL路径。返回值是一个Call类型变量,其中的范型参数定义了返回结果的类型。
3 生成接口对象
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
GitHub github = retrofit.create(GitHubService.class);
上面的代码通过建造者模式先生成Retrofit对象实例,再利用retrofit实例的create方法创建第2步接口定义的实例对象github。
4 发起请求
// Create a call instance for looking up Retrofit contributors.
Call<List<Contributor>> call = github.contributors("square", "retrofit");
// 发起异步请求
call.enqueue(new Callback<List<Contributor>>() {
//请求成功时回调
@Override
public void onResponse(Call<List<Contributor>> call,
Response<List<Contributor>> response) {
//请求处理,输出结果
response.body().show();
}
//请求失败时候的回调
@Override
public void onFailure(Call<Reception> call, Throwable throwable) {
System.out.println("连接失败");
}
});
// 发起同步请求
List<Contributor> contributors = call.execute().body();
for (Contributor contributor : contributors) {
System.out.println(contributor.login + " (" + contributor.contributions + ")");
}
利用上面的GitHubService实例对象,调用定义的接口方法得到Call对象。
call.enqueue 发起异步请求,在回调中处理响应。
call.execute 发起同步请求,等请求返回后再处理Response。
二 创建代理对象
1 创建接口对象
1.1Retrofit
上面的使用中我们创建了接口,通过retrofit.create(GitHubService.class);
就得到了接口GitHubService对应的实现类的实例对象。要学习Retrofit源码,我们先从这个create方法进行入手。
public <T> T create(final Class<T> service) {
// 检查传入的service是否符合规则,要求service必须是一个接口,并且这个接口不能继承其他接口。
Utils.validateServiceInterface(service);
// validateEagerly 标志是否提前缓存服务接口类声明的方法,是的话就从缓存中查找对象实例了。
if (validateEagerly) {
eagerlyValidateMethods(service);
}
// 使用Java的动态代理的创建一个实现了service接口的代理类。
// 传入类加载器、实现的接口数组、以及InvocationHandler
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
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);
}
});
}
2 JDK动态代理
2.1 Proxy
接下来我们看下Java的动态代理如何生成对象的。
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,
InvocationHandler h)throws IllegalArgumentException{
// 判断空逻辑
Objects.requireNonNull(h);
// 复制一份传入的接口数组,防止外部数组改变影响代理过程,这里思想很好
final Class<?>[] intfs = interfaces.clone();
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
/*
* Look up or generate the designated proxy class.
* 传入类加载器和接口数组,这里就是生成字节码对象
*/
Class<?> cl = getProxyClass0(loader, intfs);
/*
* Invoke its constructor with the designated invocation handler.
*/
try {
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
// 设置权限
if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
// 最终通过字节码对象的构造方法传入所需参数,生成所需对象。
// 这个参数就是InvocationHandler
return cons.newInstance(new Object[]{h});
} catch (IllegalAccessException|InstantiationException e) {
throw new InternalError(e.toString(), e);
......
}
上面通过getProxyClass0(loader, intfs)拿到了可以代理累对象的Class。可以继续深入看一下这个如何实现的。
/**
* Generate a proxy class. Must call the checkProxyAccess method
* to perform permission checks before calling this.
* 明确说明在调用这个方法前,必须要检查权限
*/
private static Class<?> getProxyClass0(ClassLoader loader,Class<?>... interfaces) {
// 检查接口数组数量
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
}
// If the proxy class defined by the given loader implementing
// the given interfaces exists, this will simply return the cached copy;
// otherwise, it will create the proxy class via the ProxyClassFactory
// 提示如果缓存中存在所需的Class对象,则直接返回;如果没有,则通过ProxyClassFactory工厂创建一个。
return proxyClassCache.get(loader, interfaces);
}
2.2 WeakCache
接下来看下这个proxyClassCache的实现,以及ProxyClassFactory的,首先查看WeakCache中的get方法
WeakCache 是Proxy中的缓存类,根据传入的类加载器和接口数组建立二级缓存,一级缓存的key是由类加载器生成,二级缓存的key是由接口数组生成。缓存的值是WeakCache中Factory创建的Class对象。
这个缓存类有意思的地方在于,一级缓存Key 和 二级缓存中的Value 是弱引用,二级缓存的Key是强引用。
final class WeakCache<K, P, V> {
// Reference引用队列
private final ReferenceQueue<K> refQueue = new ReferenceQueue<>();
// 缓存实现,一级缓存的key是由类加载器生成,支持为null;
// 二级缓存的key由接口数组生成,
private final ConcurrentMap<Object, ConcurrentMap<Object, Supplier<V>>> map
= new ConcurrentHashMap<>();
// reverseMap记录了缓存的Class构建是否可用,用于实现缓存的过期机制
private final ConcurrentMap<Supplier<V>, Boolean> reverseMap
= new ConcurrentHashMap<>();
// 生成二级缓存Key的工厂,使用类加载器+接口列表生成key(key, parameter) -> sub-key
private final BiFunction<K, P, ?> subKeyFactory;
// 生成二级缓存Vlaue的工厂,使用类加载器+接口列表生成Value(key, parameter) -> value
private final BiFunction<K, P, V> valueFactory;
// 构造函数就需要传入两个工厂类
public WeakCache(BiFunction<K, P, ?> subKeyFactory,
BiFunction<K, P, V> valueFactory) {
this.subKeyFactory = Objects.requireNonNull(subKeyFactory);
this.valueFactory = Objects.requireNonNull(valueFactory);
}
。。。。
}
大致了解了WeakCache的数据结构,我们下来看下其中的get方法。
public V get(K key, P parameter) {
// 接口不能为空
Objects.requireNonNull(parameter);
// 清除过期的缓存
expungeStaleEntries();
// 生成一级缓存的Key,CacheKey是内部类,等下会解析
Object cacheKey = CacheKey.valueOf(key, refQueue);
// lazily install the 2nd level valuesMap for the particular cacheKey
// 根据一级缓存的Key,拿到二级缓存。
ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
// 如果二级缓存为空,则创建新的二级缓存
if (valuesMap == null) {
// 以CAS方式放入, 如果不存在则放入,否则返回原先的值
ConcurrentMap<Object, Supplier<V>> oldValuesMap
= map.putIfAbsent(cacheKey,valuesMap = new ConcurrentHashMap<>());
// 如果oldValuesMap有值, 说明放入失败
// ??? 什么情况下会get为空,而putIfAbsent又包含旧值。
if (oldValuesMap != null) {
valuesMap = oldValuesMap;
}
}
// 生成二级缓存的key,
Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
// 拿到二级缓存值
Supplier<V> supplier = valuesMap.get(subKey);
Factory factory = null;
// 轮询条件,直到return为止。
while (true) {
if (supplier != null) {
// supplier might be a Factory or a CacheValue<V> instance
// 这个supplier有可能是缓存的,也有可能是在循环中新创建的supplier工厂
V value = supplier.get();
if (value != null) {
return value;
}
}
// else no supplier in cache
// or a supplier that returned null (could be a cleared CacheValue
// or a Factory that wasn't successful in installing the CacheValue)
// lazily construct a Factory
// 创建一个Factory,作为supplier,最终在这个factory创建了字节码
if (factory == null) {
factory = new Factory(key, parameter, subKey, valuesMap);
}
if (supplier == null) {
// 说明二级缓存的值为null,所以将刚创建的factory作为supplier
supplier = valuesMap.putIfAbsent(subKey, factory);
if (supplier == null) {
// successfully installed Factory
supplier = factory;
}
// else retry with winning supplier
// 其它线程有可能修改了二级缓存对应的值,
} else {
// 使用新的factory替换旧有的supplier
if (valuesMap.replace(subKey, supplier, factory)) {
// successfully replaced
// cleared CacheEntry / unsuccessful Factory
// with our Factory
supplier = factory;
} else {
// retry with current supplier
// 替换失败则使用之前的值
supplier = valuesMap.get(subKey);
}
}
}
}
线程安全
proxyClassCache是Proxy中的一个静态成员变量,在调用proxyClassCache的get方法时也没有加锁,它是如何保证线程安全的呢?首先WeakCache中负责缓存的容器是个ConcurrentMap,实际上个ConcurrentHashMap实例对象。将线程安全问题委托给了实际存储数据的容器。
2.3 KeyFactory
在上面的代码中,二级缓存的Key是通过构造函数传入的KeyFactory创建的,KeyFactory在构造函数时存储在subKeyFactory中。
// 生成二级缓存的key, Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
KeyFactory是Proxy中的静态内部类。
/**
* A function that maps an array of interfaces to an optimal key where
* Class objects representing interfaces are weakly referenced.
*/
private static final class KeyFactory
implements BiFunction<ClassLoader, Class<?>[], Object>
{
@Override
public Object apply(ClassLoader classLoader, Class<?>[] interfaces) {
switch (interfaces.length) {
case 1: return new Key1(interfaces[0]); // the most frequent
case 2: return new Key2(interfaces[0], interfaces[1]);
case 0: return key0;
default: return new KeyX(interfaces);
}
}
}
KeyFactory的设计很有意思,在apply中区分了1个接口、2个接口、0个接口、3个及以上接口这几种情况,为什么这么区分呢? 因为大多数情况是类实现了1个接口、其次是2个接口、再其次是实现了0个接口,实现3个及以上接口的情况最少。根据统计来优化了代码,提高了执行效率。
既然返回的对象要作为HashMap的Key,那就必须要实现hashCode和equals方法。所以继续啊看下Key1的实现
/*
* a key used for proxy class with 1 implemented interface
*/
private static final class Key1 extends WeakReference<Class<?>> {
private final int hash;
Key1(Class<?> intf) {
super(intf);
this.hash = intf.hashCode();// 使用接口数组的hashcode
}
@Override
public int hashCode() {
return hash;
}
@Override
public boolean equals(Object obj) {
Class<?> intf;
return this == obj ||
obj != null &&
obj.getClass() == Key1.class &&
(intf = get()) != null &&
intf == ((Key1) obj).get();
}
}
判断是否相等使用的是 地址->类型->值的比较逻辑。其中Key2 和KeyX的逻辑类似,key0是个静态变量,就是一个Object对象。
2.4 Factory
在二级缓存中使用生成的key可以拿到二级缓存的值,找个值实际上是个Factory类型,位于WeakCache中。
最终由接口生成的代理类,就是在这个Factory中生成的。
/**
* A factory {@link Supplier} that implements the lazy synchronized
* construction of the value and installment of it into the cache.
*/
private final class Factory implements Supplier<V> {
private final K key;// 类加载器
private final P parameter;// 接口列表数组
private final Object subKey;// 二级缓存的key
private final ConcurrentMap<Object, Supplier<V>> valuesMap;// 二级缓存map
Factory(K key, P parameter, Object subKey,
ConcurrentMap<Object, Supplier<V>> valuesMap) {
this.key = key;
this.parameter = parameter;
this.subKey = subKey;
this.valuesMap = valuesMap;
}
// 这个方法是在通过二级缓存的key拿到工厂后,从工厂中获取Class对象时。
// 需要为get方法加锁
@Override
public synchronized V get() { // serialize access
// 再次检查二级缓存中存储的工厂是不是当前工厂。
Supplier<V> supplier = valuesMap.get(subKey);
if (supplier != this) {
// something changed while we were waiting:
// might be that we were replaced by a CacheValue
// or were removed because of failure ->
// return null to signal WeakCache.get() to retry
// the loop
// 如果不是当前工厂,说明当前工厂已经失效了。返回为null让外层循环继续。
return null;
}
// else still us (supplier == this)
// create new value
V value = null;
try { // 当前工厂委托构造时传入的valueFactory去构建字节码对象。
value = Objects.requireNonNull(valueFactory.apply(key, parameter));
} finally {
if (value == null) { //构建失败,就删除当前二级缓存
valuesMap.remove(subKey, this);
}
}
// the only path to reach here is with non-null value
assert value != null;
// wrap value with CacheValue (WeakReference)
// 使用弱引用包装刚才生成的字节码对象。
CacheValue<V> cacheValue = new CacheValue<>(value);
// 将包装后的字节码对象保存进二级缓存中,
if (valuesMap.replace(subKey, this, cacheValue)) {
// 将包装后的字节码对象存入,是否过期的map中,标记为true。
reverseMap.put(cacheValue, Boolean.TRUE);
} else {
throw new AssertionError("Should not reach here");
}
// 最后返回的是没有被弱引用包装的字节码对象。
return value;
}
}
上面的代码Factory的构造方法和get方法都是在WeakCache中的get方法的循环中调用的,fatory的get方法需要使用同步,保证当前二级缓存中的缓存的factory就是当前对象本身。验证通过之后就交由valueFactory去创建代理类的字节码对象了。此时又会判断构建是否成功,如果不成功说明工厂有问题,从缓存中删除当前工厂。
如果生成成功,则首先生成包装类,将包装后的Class对象存到二级缓存中去;其次又将包装对象放到reverseMap中,用于标记是否过期。
2.5 ProxyClassFactory
最后来到了我们的重头戏,Proxy类中的ProxyClassFactory内部类是创建字节码对象的幕后黑手。
/**
* A factory function that generates, defines and returns the proxy class given
* the ClassLoader and array of interfaces.
*/
private static final class ProxyClassFactory
implements BiFunction<ClassLoader, Class<?>[], Class<?>>
{
// 定义了这个工厂创建的代理类字节码对象的名称前缀。
private static final String proxyClassNamePrefix = "$Proxy";
// 使用原子类来生成代理类的序号,保持其为唯一代理类。
private static final AtomicLong nextUniqueNumber = new AtomicLong();
@Override
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
// 先验证传入的接口数组是否一致;IdentityHashMap
Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
for (Class<?> intf : interfaces) {
/*
* Verify that the class loader resolves the name of this
* interface to the same Class object.
* 判断传入的接口类是否可以通过类加载器加载。
*/
Class<?> interfaceClass = null;
try {
interfaceClass = Class.forName(intf.getName(), false, loader);
} catch (ClassNotFoundException e) {
}
// 类加载器加载的接口字节码对象和数组中传入的接口字节码对象是否一致
if (interfaceClass != intf) {
throw new IllegalArgumentException(
intf + " is not visible from class loader");
}
/*
* Verify that the Class object actually represents an
* interface. 校验加载的接口字节码对象是否是接口类型。
*/
if (!interfaceClass.isInterface()) {
throw new IllegalArgumentException(
interfaceClass.getName() + " is not an interface");
}
/*
* Verify that this interface is not a duplicate.
* 校验加载的字节码对象是否是重复的,IdentityHashMap中key是否相等,比较的是地址是否相等,
* 地址不同则认为不重复。
*/
if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
throw new IllegalArgumentException(
"repeated interface: " + interfaceClass.getName());
}
}
// 生成代理类的包名
String proxyPkg = null; // package to define proxy class in
// 生成代理类的访问标记符 public final
int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
/*
* Record the package of a non-public proxy interface so that the
* proxy class will be defined in the same package. Verify that
* all non-public proxy interfaces are in the same package.
* 遍历接口数组,生成包名
*/
for (Class<?> intf : interfaces) {
// 获取接口的访问标记符,
int flags = intf.getModifiers();
// 如果是非public接口,则要对比下多个非public的接口的包名是否一致。不一致要报错。
if (!Modifier.isPublic(flags)) {
// 如果有非public接口,则生成的代理类对象就不能成public的,重新定义访问标记
accessFlags = Modifier.FINAL;
String name = intf.getName();
int n = name.lastIndexOf('.');
String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
// 如果代理类包名为空,则使用接口包名。
if (proxyPkg == null) {
proxyPkg = pkg;
// 当然如果出现多个非public接口,并且包名不同,则报错。
} else if (!pkg.equals(proxyPkg)) {
throw new IllegalArgumentException(
"non-public interfaces from different packages");
}
}
}
// 如果没有非public接口。包名就随意了,使用默认包名com.sun.proxy
if (proxyPkg == null) {
// if no non-public proxy interfaces, use com.sun.proxy package
proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
}
/*
* Choose a name for the proxy class to generate.
* 使用包名+代理类前缀+编号 最终生成代理类全路径名称。
*/
long num = nextUniqueNumber.getAndIncrement();
String proxyName = proxyPkg + proxyClassNamePrefix + num;
/*
* Generate the specified proxy class.
* 重点来了,使用ProxyGenerator创建最终的代理类的字节码。
*/
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);
try {// 解析二进制字节码生成相应的Class 实例。
return defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
} catch (ClassFormatError e) {
/*
* A ClassFormatError here means that (barring bugs in the
* proxy class generation code) there was some other
* invalid aspect of the arguments supplied to the proxy
* class creation (such as virtual machine limitations
* exceeded).
*/
throw new IllegalArgumentException(e.toString());
}
}
}
上面的ProxyClassFactory类,首先检查接口数组是否符合规则,
(1)判断传入的接口类是否可以通过传入的类加载器加载,以及加载后是否和原接口类一致。
(2)检查传入的接口类类对象是否都是接口类型。
(3)检查数组中的接口是否有重复。
接口校验都通过后,就开始准备代理类的包名和访问修饰符了。
默认包名为com.sun.proxy,默认访问修饰符为 public final
(1)当所有接口都是public类型时,包名和访问修饰符使用默认值。
(2)当有接口是非public时,包名变为接口包名,访问修饰符变为 final
(3)当有多个非public的接口的包名不同时,报错。
确定包名后通过包名+$Proxy+序号生成最终的代理类全路径名。
最后通过ProxyGenerator.generateProxyClass方法生成代理类对象的二进制字节码。再通过native方法defineClass0生成代理类Class实例。
2.6 ProxyGenerator
在上面ProxyClassFactory类的讲解中我们提到最终是ProxyGenerator.generateProxyClass生成了代理类二进制流,具体是怎么生成的呢? 今天就来探究一下源码。这个类在package sun.misc;包下。
// 静态方法内部第一步还是创建ProxyGenerator对象。
public static byte[] generateProxyClass(final String var0, Class<?>[] var1, int var2) {
ProxyGenerator var3 = new ProxyGenerator(var0, var1, var2);
// 还是generateClassFile方法生成了二进制流
final byte[] var4 = var3.generateClassFile();
if (saveGeneratedFiles) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
try {
int var1 = var0.lastIndexOf(46);
Path var2;
if (var1 > 0) {
Path var3 = Paths.get(var0.substring(0, var1).replace('.', File.separatorChar));
Files.createDirectories(var3);
var2 = var3.resolve(var0.substring(var1 + 1, var0.length()) + ".class");
} else {
var2 = Paths.get(var0 + ".class");
}
Files.write(var2, var4, new OpenOption[0]);
return null;
} catch (IOException var4x) {
throw new InternalError("I/O exception saving generated file: " + var4x);
}
}
});
}
return var4;
}
生成二进制流
private byte[] generateClassFile() {
// 首先为代理类生成hashCode、equals、toString方法
this.addProxyMethod(hashCodeMethod, Object.class);
this.addProxyMethod(equalsMethod, Object.class);
this.addProxyMethod(toStringMethod, Object.class);
Class[] var1 = this.interfaces;
int var2 = var1.length;
int var3;
Class var4;
// 遍历接口数组,遍历每个接口中的方法,并将这些方法添加到代理类中。
for(var3 = 0; var3 < var2; ++var3) {
var4 = var1[var3];
Method[] var5 = var4.getMethods();
int var6 = var5.length;
for(int var7 = 0; var7 < var6; ++var7) {
Method var8 = var5[var7];
this.addProxyMethod(var8, var4);
}
}
Iterator var11 = this.proxyMethods.values().iterator();
// 遍历代理对象的方法列表,检查是否有相同方法签名,而返回类型不同的情况。
List var12;
while(var11.hasNext()) {
var12 = (List)var11.next();
checkReturnTypes(var12);
}
// 组装生成代理类Class文件所需的字段和方法信息。
Iterator var15;
try {
// 添加构造方法,这个构造方法是固定的,传入的是InvocationHandler
this.methods.add(this.generateConstructor());
var11 = this.proxyMethods.values().iterator();
while(var11.hasNext()) {
var12 = (List)var11.next();
var15 = var12.iterator();
while(var15.hasNext()) {
ProxyGenerator.ProxyMethod var16 = (ProxyGenerator.ProxyMethod)var15.next();
// 添加代理类的字段
this.fields.add(new ProxyGenerator.FieldInfo(var16.methodFieldName, "Ljava/lang/reflect/Method;", 10));
// 生成代理方法
this.methods.add(var16.generateMethod());
}
}
// 添加代理类的静态字段初始化方法
this.methods.add(this.generateStaticInitializer());
} catch (IOException var10) {
throw new InternalError("unexpected I/O Exception", var10);
}
// 验证方法数量和字段数量不能超过65535
if (this.methods.size() > 65535) {
throw new IllegalArgumentException("method limit exceeded");
} else if (this.fields.size() > 65535) {
throw new IllegalArgumentException("field limit exceeded");
} else {
// 验证代理类的全限定定名是否在常量池中,.切换为/
this.cp.getClass(dotToSlash(this.className));
// 验证代理类父类的全限定名是否在常量池中
this.cp.getClass("java/lang/reflect/Proxy");
var1 = this.interfaces;
var2 = var1.length;
// 验证代理类接口列表的全限定名
for(var3 = 0; var3 < var2; ++var3) {
var4 = var1[var3];
this.cp.getClass(dotToSlash(var4.getName()));
}
// 设置常量池为只读
this.cp.setReadOnly();
ByteArrayOutputStream var13 = new ByteArrayOutputStream();
DataOutputStream var14 = new DataOutputStream(var13);
try {
// 1.写入魔数
var14.writeInt(-889275714);
// 2.写入次版本号
var14.writeShort(0);
// 3.写入主版本号
var14.writeShort(49);
// 4.写入常量池
this.cp.write(var14);
// 5.写入访问修饰符
var14.writeShort(this.accessFlags);
// 6.写入类名在常量池中的索引
var14.writeShort(this.cp.getClass(dotToSlash(this.className)));
// 7.写入父类索引
var14.writeShort(this.cp.getClass("java/lang/reflect/Proxy"));
// 8.写入接口数量
var14.writeShort(this.interfaces.length);
// 9.遍历接口,写入每个接口的索引
Class[] var17 = this.interfaces;
int var18 = var17.length;
for(int var19 = 0; var19 < var18; ++var19) {
Class var22 = var17[var19];
var14.writeShort(this.cp.getClass(dotToSlash(var22.getName())));
}
// 10.写入字段数量
var14.writeShort(this.fields.size());
· // 11.遍历字段数组,将字段写入
var15 = this.fields.iterator();
while(var15.hasNext()) {
ProxyGenerator.FieldInfo var20 = (ProxyGenerator.FieldInfo)var15.next();
var20.write(var14);
}
// 12.写入方法数量
var14.writeShort(this.methods.size());
// 13.便利方法数组,将方法写入
var15 = this.methods.iterator();
while(var15.hasNext()) {
ProxyGenerator.MethodInfo var21 = (ProxyGenerator.MethodInfo)var15.next();
var21.write(var14);
}
// 14.写入属性计数值,代理类Class 文件没有属性则为0
var14.writeShort(0);
return var13.toByteArray();
} catch (IOException var9) {
throw new InternalError("unexpected I/O Exception", var9);
}
}
}
上面的流程很清楚了,generateClassFile就是根据代理类全路径名、实现的接口数组、类对象访问修饰符生成了代理类,先收集了代理类需要实现的方法,其次生成代理类的方法和字段信息,最后按照Class文件的规范,通过代码拼接了代理类的Class文件,下面我们写一个demo来查看下最终生成的Class文件。值得注意的是上面的构造方法是固定的,默认传入InvocationHandler对象。
public static void main(String[] args) throws IOException {
// 1.准备代理类全路径名
String proxyName = "wux.text.WxProxy";
// 2.代理类要实现的接口数组
Class[] interfaces = new Class[]{WxInterfaceTest.class};
// 3.访问修饰符号
int modifier = Modifier.PUBLIC|Modifier.FINAL;
// 4.生成代理类字节码二进制流
byte[] classResult = ProxyGenerator.generateProxyClass(proxyName,interfaces,modifier);
// 5.将生成的字节码二进制流写入文件
FileOutputStream fileOutputStream = new FileOutputStream("WuxProxy.class");
fileOutputStream.write(classResult);
fileOutputStream.flush();
fileOutputStream.close();
}
运行上面的代码可以得到WuxProxy.class文件,反编译之后如下,
package wux.text;
import com.bennyhuo.retrofit.tutorials.WxInterfaceTest;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
// 代理类继承Proxy,
public final class WxProxy extends Proxy implements WxInterfaceTest {
// 2. 生成静态方法
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m0;
// 1.构造函数需要传入InvocationHandler,
public WxProxy(InvocationHandler var1) throws {
super(var1);
}
// 3. 生成代理方法
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 void sayHello() throws {
try {// 代理方法的具体执行还是依赖,InvocationHandler的invoke方法
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
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 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"));
m3 = Class.forName("com.bennyhuo.retrofit.tutorials.WxInterfaceTest").getMethod("sayHello");
m2 = Class.forName("java.lang.Object").getMethod("toString");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
(1)上面生成的代理类默认继承Proxy,由于Java单继承的限制,所以JDK动态代理都只能用于接口。
(2)代理类方法的执行最终都会执行到h.invoke,将代理方法的调用转发到InvocationHandler的invoke中,具体执行的是invoke中的代码。会传入代理对象实例、方法、参数数组等。
3 Cglib动态代理
JDK自带的动态代理只支持接口,Cglib的动态代理实现了对类的动态代理。
“代理”的目的是构造一个和被代理的对象有同样行为的对象,一个对象的行为是在类中定义的,对象只是类的实例。所以构造代理,不一定非得通过持有、包装对象这一种方式。
通过“继承”可以继承父类所有的公开方法,然后可以重写这些方法,在重写时对这些方法增强,这就是cglib的思想。根据里氏代换原则(LSP),父类需要出现的地方,子类可以出现,所以cglib实现的代理也是可以被正常使用的。
首先引入依赖
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.10</version>
</dependency>
首先我们创建一个被代理的类。
public class CglibDemoBaseCalss {
public String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
使用Cglib的流程
public static void main(String[] args) {
// 1. cglib通过Enhancer来进行代理类的配置和创建,enhancer是Cglib的字节码增强器
// 可以对代理类进行增强。
Enhancer enhancer = new Enhancer();
// 2. 设置要代理的类
enhancer.setSuperclass(CglibDemoBaseCalss.class);
// 3. cglib 也支持对接口的代理
enhancer.setInterfaces(new Class[]{WxInterfaceTest.class});
// 4. 设置方法调用时的回调,类似于InvocationHandler的invoke,可以让代理类决定方法调用的最终表现
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
System.out.println("before:" + method.getName());
Object result = proxy.invokeSuper(obj, args);
System.out.println("after: " + method.getName());
return result;
}
});
// 5. 调用生成的代理类的方法
CglibDemoBaseCalss cglibDemoBaseCalss = (CglibDemoBaseCalss) enhancer.create();
cglibDemoBaseCalss.setName("代理测试:");
cglibDemoBaseCalss.sayName();
}
输出结果为:
before:setName
after: setName
before:sayName
代理测试:
after: sayName
Cglib实现动态代理的原理和JDK动态代理类似,都是生成代理类的字节码文件,再加载进内存生成实例对象。下面看下具体实现流程。
3.1 Enhancer
Enhancer是通过create方法创建的代理类对象,这里就从此处进行源码的解析。
/**
* Generate a new class if necessary and uses the specified
* callbacks (if any) to create a new object instance.
* Uses the no-arg constructor of the superclass.
* @return a new instance
*/
public Object create() {
classOnly = false;
argumentTypes = null;
return createHelper();
}
接下来看下createHelper方法的实现,
private Object createHelper() {
// 进行预检查
preValidate();
// 创建类并实例化对象
Object key = KEY_FACTORY.newInstance((superclass != null) ? superclass.getName() : null,
ReflectUtils.getNames(interfaces),
filter == ALL_ZERO ? null : new WeakCacheKey<CallbackFilter>(filter),
callbackTypes,
useFactory,
interceptDuringConstruction,
serialVersionUID);
this.currentKey = key;
Object result = super.create(key);
return result;
}
这里KEY_FACTORY是个什么鬼,直接就生成对象了,继续看下这个常量的定义
private static final EnhancerKey KEY_FACTORY =
(EnhancerKey)KeyFactory.create(EnhancerKey.class, KeyFactory.HASH_ASM_TYPE, null);
这个代码有点意思,EnhancerKey是个接口,KeyFactory.create返回的是KeyFactory类型,这怎么强转呢?除非返回的KeyFactory实例实现了这个接口。再往后看果真传入了EnhancerKey.class作为参数,大概率是用作增强KeyFactory。
3.2 KeyFactory
接下来看下KeyFactory中的create方法。
public static KeyFactory create(Class keyInterface, KeyFactoryCustomizer first, List<KeyFactoryCustomizer> next) {
return create(keyInterface.getClassLoader(), keyInterface, first, next);
}
内部调用的还是create方法,
public static KeyFactory create(ClassLoader loader, Class keyInterface, KeyFactoryCustomizer customizer,List<KeyFactoryCustomizer> next) {
Generator gen = new Generator();
// 设置代理类实现的接口
gen.setInterface(keyInterface);
// 这部分暂时还不知道是什么
if (customizer != null) {
gen.addCustomizer(customizer);
}
if (next != null && !next.isEmpty()) {
for (KeyFactoryCustomizer keyFactoryCustomizer : next) {
gen.addCustomizer(keyFactoryCustomizer);
}
}
// 配置类加载器
gen.setClassLoader(loader);
return gen.create();
}
3.3 Generator
这个Generator是KeyFactory的内部类,继承了AbstractClassGenerator。此处无非是设置一些参数,最后还是调用create方法生成我们想要的KeyFactory。那继续往下看
public KeyFactory create() {
setNamePrefix(keyInterface.getName());
return (KeyFactory)super.create(keyInterface.getName());
}
3.4 AbstractClassGenerator
上面的Generator调用的create方法最终还是调用父类的create方法,这里看下父类实现。
protected Object create(Object key) {
try {
// 获取类加载器,其实就是上一步在KeyFactory中设置的类加载器
ClassLoader loader = getClassLoader();
Map<ClassLoader, ClassLoaderData> cache = CACHE;
// 获取缓存中的类加载数据
ClassLoaderData data = cache.get(loader);
// 加锁进行双重检查,
if (data == null) {
synchronized (AbstractClassGenerator.class) {
cache = CACHE;
data = cache.get(loader);
if (data == null) {
// 确定缓存中没有类加载器才创建新的缓存数据
Map<ClassLoader, ClassLoaderData> newCache = new WeakHashMap<ClassLoader, ClassLoaderData>(cache);
// 创建新的类加载数据
data = new ClassLoaderData(loader);
newCache.put(loader, data);
// 跟新缓存
CACHE = newCache;
}
}
}
this.key = key;
// 这一步很关键,ClassLoaderData的get返回的才是我们增强的代理类Class对象。
Object obj = data.get(this, getUseCache());
if (obj instanceof Class) {
return firstInstance((Class) obj);
}
return nextInstance(obj);
} catch (RuntimeException e) {
throw e;
} catch (Error e) {
throw e;
} catch (Exception e) {
throw new CodeGenerationException(e);
}
}
在上面的create方法中,首先根据类加载器作为key去检查缓存的字节码对象数据。找到缓存的ClassLoaderData又从中获取字节码对象。
3.5 ClassLoaderData
ClassLoaderData是AbstractClassGenerator的内部类,这的get方法显式持有了外部类的引用,调用的也是外部类的generate方法。
public Object get(AbstractClassGenerator gen, boolean useCache) {
if (!useCache) {
// 不使用缓存情况下生成字节码对象的过程
return gen.generate(ClassLoaderData.this);
} else {
Object cachedValue = generatedClasses.get(gen);
return gen.unwrapCachedValue(cachedValue);
}
}
所以最后我们还是要回到AbstractClassGenerator类中,查看具体的实现。
protected Class generate(ClassLoaderData data) {
Class gen;
// 这里的CURRENT 是个ThreadLocal类型,具体作用在暂时还不清楚
Object save = CURRENT.get();
CURRENT.set(this);
try {
// 1.获取类加载器
ClassLoader classLoader = data.getClassLoader();
if (classLoader == null) {// 为空就报错
throw new IllegalStateException("ClassLoader is null while trying to define class " +
getClassName() + ". It seems that the loader has been expired from a weak reference somehow. Please file an issue at cglib's issue tracker.");
}
// 2.对类加载器加锁,生成代理类名称。这里的代理类名称其实是可以通过namingPolicy定义的
synchronized (classLoader) {
String name = generateClassName(data.getUniqueNamePredicate());
data.reserveName(name);
this.setClassName(name);
}
// 3.先尝试通过类加载器加载代理类字节码对象,有的话就直接返回了
if (attemptLoad) {
try {
gen = classLoader.loadClass(getClassName());
return gen;
} catch (ClassNotFoundException e) {
// ignore
}
}
// 4. 之前没有加载过代理类的字节码对象,这里进行代理类Class二进制流的创建过程。
byte[] b = strategy.generate(this);
String className = ClassNameReader.getClassName(new ClassReader(b));
ProtectionDomain protectionDomain = getProtectionDomain();
synchronized (classLoader) { // just in case
if (protectionDomain == null) {
gen = ReflectUtils.defineClass(className, b, classLoader);
} else {
gen = ReflectUtils.defineClass(className, b, classLoader, protectionDomain);
}
}
return gen;
} catch (RuntimeException e) {
throw e;
} catch (Error e) {
throw e;
} catch (Exception e) {
throw new CodeGenerationException(e);
} finally {
CURRENT.set(save);
}
}
终于见到了Class文件的生成过程,主要分为这几步:
(1)获取类加载器,顺便进行异常检查。
(2)根据类加载器生成代理类名称。
String name = generateClassName(data.getUniqueNamePredicate());
private String generateClassName(Predicate nameTestPredicate) {
return namingPolicy.getClassName(namePrefix, source.name, key, nameTestPredicate);
}
private NamingPolicy namingPolicy = DefaultNamingPolicy.INSTANCE;
/**
* Override the default naming policy.
* @see DefaultNamingPolicy
* @param namingPolicy the custom policy, or null to use the default
*/
public void setNamingPolicy(NamingPolicy namingPolicy) {
if (namingPolicy == null)
namingPolicy = DefaultNamingPolicy.INSTANCE;
this.namingPolicy = namingPolicy;
}
(3)检查之前是否加载过代理类,有的话就直接返回了。
(4)通过strategy进行代理类的生成。
byte[] b = strategy.generate(this);
private GeneratorStrategy strategy = DefaultGeneratorStrategy.INSTANCE;
/**
* Override the default naming policy.
* @see DefaultNamingPolicy
* @param namingPolicy the custom policy, or null to use the default
*/
public void setNamingPolicy(NamingPolicy namingPolicy) {
if (namingPolicy == null)
namingPolicy = DefaultNamingPolicy.INSTANCE;
this.namingPolicy = namingPolicy;
}
上面的namingPolicy 和 strategy都是AbstractClassGenerator的成员变量,大多数情况下都使用默认配置,但我们也可以替换为自己的实现。
自定义NamingPolicy和GeneratorStrategy,这里我们自定义一下这两块的逻辑
// 通过
class MyNameAndBytesFactory implements NamingPolicy,GeneratorStrategy{
private NamingPolicy mNamingPolicy = new DefaultNamingPolicy();
private GeneratorStrategy mGeneratorStrategy = new DefaultGeneratorStrategy();
private String name;
@Override
public byte[] generate(ClassGenerator cg) throws Exception {
byte[] result = mGeneratorStrategy.generate(cg);
FilesKt.writeBytes(new File(name+".class"),result);
return result;
}
@Override
public String getClassName(String prefix, String source, Object key, Predicate names) {
name = mNamingPolicy.getClassName(prefix,source,key,names);
return name;
}
}
MyNameAndBytesFactory myNameAndBytesFactory = new MyNameAndBytesFactory();
enhancer.setStrategy(myNameAndBytesFactory);
enhancer.setNamingPolicy(myNameAndBytesFactory);
上面我们首先在方法内部实现了一个本地类,实现NamingPolicy和GeneratorStrategy接口,当然这里使用的是代理的方式,字节码和名称还是依赖于默认的实现,在这里我们将字节码保存为文件,方便后面分析字节码结构。
在生成的字节码文件中
private MethodInterceptor CGLIB$CALLBACK_0;
public final void sayName() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (this.CGLIB$CALLBACK_0 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
var10000.intercept(this, CGLIB$sayName$2$Method, CGLIB$emptyArgs, CGLIB$sayName$2$Proxy);
} else {
super.sayName();
}
}
因为我们设置setCallback是MethodInterceptor类型,可以看出生成的动态代理类中也有MethodInterceptor类型的成员变量,因为这个变量不为空,所以最终走的interceptor的intercept方法。
4 动态代理区别
JDK动态代理只支持接口,方法调用是反射调用,接口功能单一。
CgLib动态代理支持接口和类(非final),支持反射和直接调用(FastClass),代理策略丰富。
动态代理一般是运行时生成字节码加载类再创建出对象。
静态代理是在运行时之前,编译阶段就确定代理结构。
编译期生成字节码
三 调用接口方法
1 Retrofit
继续研究Retrofit
// Create a call instance for looking up Retrofit contributors.
Call<List<Contributor>> call = github.contributors("square", "retrofit");
在由Retrofit通过动态代理生成了接口对象后,我们会调用实例对象中的方法时,代码的执行路径如何呢?首先回忆下动态代理对象创建过程。
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();
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);
}
});
}
所有接口方法的调用实际上都是会调用InvocationHandler中的invoke方法,因为代理的是接口,所以会走到loadServiceMethod这里
private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();
ServiceMethod<?> loadServiceMethod(Method method) {
ServiceMethod<?> result = serviceMethodCache.get(method);
if (result != null) return result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {// 创建最终调用的serviceMethod
result = ServiceMethod.parseAnnotations(this, method);
serviceMethodCache.put(method, result);
}
}
return result;
}
首先是从serviceMethodCache中查找指定方法,没有则加锁使用ServiceMethod.parseAnnotations(this, method);进行创建。
2 ServiceMethod
abstract class ServiceMethod<T> {
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
// 1. 解析标记请求的注解
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
// 2. 解析返回类型
Type returnType = method.getGenericReturnType();
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(method,
"Method return type must not include a type variable or wildcard: %s", returnType);
}
if (returnType == void.class) {
throw methodError(method, "Service methods cannot return void.");
}
// 3. 解析并生成ServiceMethod
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
abstract @Nullable T invoke(Object[] args);
}
创建ServiceMethod的过程主要分3步,
(1)解析接口方法注解和参数注解,生成RequestFactory。
(2)解析并检测方法返回类型是否正常。
(3)将接口方法生成对应Http请求对象。
3 RequestFactory
先看代码如何生成RequestFactory实例,这里使用的是建造者模式。
final class RequestFactory {
private final Method method;// 请求对应的接口方法
private final HttpUrl baseUrl;// 请求路径
final String httpMethod;// 请求方法
private final @Nullable String relativeUrl;// 相对路径
private final @Nullable Headers headers;// 请求头
private final @Nullable MediaType contentType;// 请求媒体类型
private final boolean hasBody;// 请求是否有body
private final boolean isFormEncoded;
private final boolean isMultipart;
private final ParameterHandler<?>[] parameterHandlers;//参数解析处理器
final boolean isKotlinSuspendFunction;
static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
return new Builder(retrofit, method).build();
}
Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
this.methodAnnotations = method.getAnnotations();// 获取方法注解
this.parameterTypes = method.getGenericParameterTypes();// 获取方法参数类型数组
this.parameterAnnotationsArray = method.getParameterAnnotations();// 获取方法注解数组,是个二维数组
}
}
RequestFactory中有诸多成员变量,都需要通过建造者继续创建,下面逐步解析创建流程。
RequestFactory build() {
// 1. 循环遍历请求方法上的注解
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
// 2. 判断请求参数以及其他参数
if (httpMethod == null) {
throw methodError(method, "HTTP method annotation is required (e.g., @GET, @POST, etc.).");
}
if (!hasBody) {
if (isMultipart) {
throw methodError(method,
"Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
}
if (isFormEncoded) {
throw methodError(method, "FormUrlEncoded can only be specified on HTTP methods with "
+ "request body (e.g., @POST).");
}
}
// 3.创建方法参数处理器
int parameterCount = parameterAnnotationsArray.length;
parameterHandlers = new ParameterHandler<?>[parameterCount];
for (int p = 0, lastParameter = parameterCount - 1; p < parameterCount; p++) {
parameterHandlers[p] =
parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == lastParameter);
}
// 4.判断是否异常
if (relativeUrl == null && !gotUrl) {
throw methodError(method, "Missing either @%s URL or @Url parameter.", httpMethod);
}
if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
throw methodError(method, "Non-body HTTP method cannot contain @Body.");
}
if (isFormEncoded && !gotField) {
throw methodError(method, "Form-encoded method must contain at least one @Field.");
}
if (isMultipart && !gotPart) {
throw methodError(method, "Multipart method must contain at least one @Part.");
}
return new RequestFactory(this);
}
- 循环遍历请求方法上的注解
要构建一个RequestFactory首先是解析接口方法的注解,源代码如下:
private void parseMethodAnnotation(Annotation annotation) {
// 解析请求方式的部分
if (annotation instanceof DELETE) {
parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
} else if (annotation instanceof GET) {
// 解析请求路径
parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
} else if (annotation instanceof HEAD) {
parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false);
} else if (annotation instanceof PATCH) {
parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true);
} else if (annotation instanceof POST) {
parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
} else if (annotation instanceof PUT) {
parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true);
} else if (annotation instanceof OPTIONS) {
parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false);
} else if (annotation instanceof HTTP) {
HTTP http = (HTTP) annotation;
parseHttpMethodAndPath(http.method(), http.path(), http.hasBody());
} else if (annotation instanceof retrofit2.http.Headers) {
String[] headersToParse = ((retrofit2.http.Headers) annotation).value();
if (headersToParse.length == 0) {
throw methodError(method, "@Headers annotation is empty.");
}
// 解析请求头注解
headers = parseHeaders(headersToParse);
} else if (annotation instanceof Multipart) {
if (isFormEncoded) {
throw methodError(method, "Only one encoding annotation is allowed.");
}
isMultipart = true;
} else if (annotation instanceof FormUrlEncoded) {
if (isMultipart) {
throw methodError(method, "Only one encoding annotation is allowed.");
}
isFormEncoded = true;
}
}
上面的代码展示了在Retrofit中可用在方法上使用的注解,以及处理方式。主要处理的请求路径生成、请求头、及其他参数。下面看下如何从方法注解和请求参数中装配出当前请求方法的URL。
private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
// 传入参数简单校验
if (this.httpMethod != null) {
throw methodError(method, "Only one HTTP method is allowed. Found: %s and %s.",
this.httpMethod, httpMethod);
}
this.httpMethod = httpMethod;
this.hasBody = hasBody;
// 如果没有注解就直接返回了,无需解析路径了
if (value.isEmpty()) {
return;
}
// 检查请求的url中有没有附带参数,及 xxxx.com?name=tony&age=18 这类在URL中的参数。
int question = value.indexOf('?');
if (question != -1 && question < value.length() - 1) {
// Ensure the query string does not have any named parameters.
String queryParams = value.substring(question + 1);
Matcher queryParamMatcher = PARAM_URL_REGEX.matcher(queryParams);
if (queryParamMatcher.find()) {
// 说明如果在URL中使用了请求参数,请不要使用动态参数,否则会提示错误。
throw methodError(method, "URL query string \"%s\" must not have replace block. "
+ "For dynamic query parameters use @Query.", queryParams);
}
}
// 保存相对路径
this.relativeUrl = value;
// 解析参数路径
this.relativeUrlParamNames = parsePathParameters(value);
}
// 将路径中的动态参数解析出来,保存到set中,所以重复的参数只会请求一次。
static Set<String> parsePathParameters(String path) {
Matcher m = PARAM_URL_REGEX.matcher(path);
Set<String> patterns = new LinkedHashSet<>();
while (m.find()) {
patterns.add(m.group(1));
}
return patterns;
}
// 对请求头进行处理
private Headers parseHeaders(String[] headers) {
Headers.Builder builder = new Headers.Builder();
for (String header : headers) {
int colon = header.indexOf(':');
if (colon == -1 || colon == 0 || colon == header.length() - 1) {
throw methodError(method,
"@Headers value must be in the form \"Name: Value\". Found: \"%s\"", header);
}
String headerName = header.substring(0, colon);
String headerValue = header.substring(colon + 1).trim();
if ("Content-Type".equalsIgnoreCase(headerName)) {
try {
contentType = MediaType.get(headerValue);
} catch (IllegalArgumentException e) {
throw methodError(method, e, "Malformed content type: %s", headerValue);
}
} else {
// 请求头中是以键值对的形式存储的。
builder.add(headerName, headerValue);
}
}
return builder.build();
}
上面的代码中将注解中的路径进行解析,取出动态参数。Retrofit中不建议在请求参数中使用动态参数。
- 生成方法参数处理器
// 3.创建方法处理器
int parameterCount = parameterAnnotationsArray.length;
parameterHandlers = new ParameterHandler<?>[parameterCount];
for (int p = 0, lastParameter = parameterCount - 1; p < parameterCount; p++) {
parameterHandlers[p] =
parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == lastParameter);
}
在RequestFactory.Builder.build() 方法中,第三步是创建方法参数处理器,下面看下具体实现流程。
// p是参数索引,parameterType是参数类型,annotations是p指向当前参数的注解数组,allowContinuation标记是否是最后一个参数
private @Nullable ParameterHandler<?> parseParameter(
int p, Type parameterType, @Nullable Annotation[] annotations, boolean allowContinuation) {
ParameterHandler<?> result = null;
//1. 当前参数注解不为空时解析注解,如果注解为空并且不是最后一个参数就返回了。
if (annotations != null) {
for (Annotation annotation : annotations) {
// 遍历并解析Retrofit定义的注解
ParameterHandler<?> annotationAction =
parseParameterAnnotation(p, parameterType, annotations, annotation);
// 非Retrofit注解就跳过继续处理下一个注解
if (annotationAction == null) {
continue;
}
// 如果一个参数上有多个Retrofit注解就抛出错误。
if (result != null) {
throw parameterError(method, p,
"Multiple Retrofit annotations found, only one allowed.");
}
// 总结一下,一个参数只能使用一个Retrofit注解。
result = annotationAction;
}
}
if (result == null) {
if (allowContinuation) {
try {
if (Utils.getRawType(parameterType) == Continuation.class) {
isKotlinSuspendFunction = true;
return null;
}
} catch (NoClassDefFoundError ignored) {
}
}
throw parameterError(method, p, "No Retrofit annotation found.");
}
return result;
}
接下来看下具体的注解处理流程。
@Nullable
private ParameterHandler<?> parseParameterAnnotation(
int p, Type type, Annotation[] annotations, Annotation annotation) {
if (annotation instanceof Url) {
...
} else if (annotation instanceof Path) {
// 1. 检查是否支持参数type类型
validateResolvableType(p, type);
// 2. 检查当前注解所属位置是否合适,比如说:Path要在Query之前,Path不能和Url混用。
if (gotQuery) {
throw parameterError(method, p, "A @Path parameter must not come after a @Query.");
}
if (gotQueryName) {
throw parameterError(method, p, "A @Path parameter must not come after a @QueryName.");
}
if (gotQueryMap) {
throw parameterError(method, p, "A @Path parameter must not come after a @QueryMap.");
}
if (gotUrl) {
throw parameterError(method, p, "@Path parameters may not be used with @Url.");
}
if (relativeUrl == null) {
throw parameterError(method, p, "@Path can only be used with relative url on @%s",
httpMethod);
}
gotPath = true;
// 3. 取出注解中参数,并校验是否在相对路径中。
Path path = (Path) annotation;
String name = path.value();
validatePathName(p, name);
// 4. 根据参数类型寻找转换器,因为不论什么类型的参数,都需要最终转化为String才行。
Converter<?, String> converter = retrofit.stringConverter(type, annotations);
// 5. 创建对应注解类型的ParameterHandler
return new ParameterHandler.Path<>(method, p, name, converter, path.encoded());
} else if (annotation instanceof Query) {
...
} else if (annotation instanceof QueryName) {
...
} else if (annotation instanceof QueryMap) {
...
} else if (annotation instanceof Header) {
...
} else if (annotation instanceof HeaderMap) {
...
} else if (annotation instanceof Field) {
...
} else if (annotation instanceof FieldMap) {
...
} else if (annotation instanceof Part) {
...
} else if (annotation instanceof PartMap) {
...
} else if (annotation instanceof Body) {
...
} else if (annotation instanceof Tag) {
...
}
return null; // Not a Retrofit annotation.
}
从parseParameterAnnotation的流程中可以看出,Retrofit的参数注解共有13个,分别是Url、Path、Query、QueryName、QueryMap、Header、HeaderMap、Field、FieldMap、Part、PartMap、Body、Tag ,解析处理流程都类似。
这类解析下参数注解的处理流程:
(1)检查是否是支持的参数类型。
(2)检查当前注解所属位置是否合适,比如说:Path要在Query之前,Path不能和Url混用。
(3) 取出注解中参数,并校验是否在相对路径中。
(4)根据参数类型寻找转换器,因为不论什么类型的参数,都需要最终转化为String才行。
(5)创建对应注解类型的ParameterHandler。
ParameterHandler是一个抽象类,这里看下其中的抽象方法apply,主要是传入RequestBuilder和value,将接口方法参数值value经过处理后添加进RequestBuilder中。
abstract class ParameterHandler<T> {
abstract void apply(RequestBuilder builder, @Nullable T value) throws IOException;
.....
}
这里看一下Path类参数的处理过程。
static final class Path<T> extends ParameterHandler<T> {
private final Method method;// 接口方法
private final int p;// 参数索引
private final String name;// 动态路径参数名称
private final Converter<T, String> valueConverter;// 参数转换器
private final boolean encoded;// 路径参数的值是否转码,就是是否将非中文进行转码
Path(Method method, int p, String name, Converter<T, String> valueConverter, boolean encoded) {
this.method = method;
this.p = p;
this.name = checkNotNull(name, "name == null");
this.valueConverter = valueConverter;
this.encoded = encoded;
}
@Override void apply(RequestBuilder builder, @Nullable T value) throws IOException {
if (value == null) {
throw Utils.parameterError(method, p,
"Path parameter \"" + name + "\" value must not be null.");
}
// 将动态参数名称和转化为字符串后的参数值添加到RequestBuilder中。
builder.addPathParam(name, valueConverter.convert(value), encoded);
}
}
上面的代码解析我们将接口方法的注解处理过程都过了一遍。将RequestFactory中的成员变量都拿到了。重新回到ServiceMethod中看下
HttpServiceMethod是如何创建的。
// 3. 解析并生成ServiceMethod
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
4.HttpServiceMethod
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
boolean continuationWantsResponse = false;
boolean continuationBodyNullable = false;
Annotation[] annotations = method.getAnnotations();
Type adapterType;
if (isKotlinSuspendFunction) {
.........
annotations = SkipCallbackExecutorImpl.ensurePresent(annotations);
} else {
// 获取适配的类型信息。这些范型实参其实存储在字节码的注释行,所以如果混淆处理了注释,就会拿不到范型实参。
// 因为在1.5添加范型时,之前的java版本已经在广泛使用了,考虑到兼容性,只能把擦除的范型实参签名放置到注释里面。
adapterType = method.getGenericReturnType();
}
// 生成callAdapter将上游传回的数据OkHttpCall<ResponseT> 转换为接口的返回类型
// 决定接口方法定义的想要什么样的回调例如:官方例子中contributors接口方法返回如下回调类型Call<List<Contributor>>
// 由回调接口发起最终请求,决定异步同步,其实最终都调用到OkHttpCall中
CallAdapter<ResponseT, ReturnT> callAdapter =
createCallAdapter(retrofit, method, adapterType, annotations);
Type responseType = callAdapter.responseType();
if (responseType == okhttp3.Response.class) {
throw methodError(method, "'"
+ getRawType(responseType).getName()
+ "' is not a valid response body type. Did you mean ResponseBody?");
}
if (responseType == Response.class) {
throw methodError(method, "Response must include generic type (e.g., Response<String>)");
}
// TODO support Unit for Kotlin?
if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
throw methodError(method, "HEAD method must use Void as response type.");
}
// 将上游的ResponseBody 转化为ResponseT,官方例子中,这里的ResponseT就是List<Contributor>
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);
okhttp3.Call.Factory callFactory = retrofit.callFactory;
if (!isKotlinSuspendFunction) {
// 最终走在这里这里
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
} else if (continuationWantsResponse) {
//noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForResponse<>(requestFactory,
callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
} else {
//noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForBody<>(requestFactory,
callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
continuationBodyNullable);
}
}
我们从后往前阅读圆满,先看parseAnnotations的返回类型CallAdapted。
static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
private final CallAdapter<ResponseT, ReturnT> callAdapter;
// 这里传入的是okhttp3.Call.Factory,在请求回来后,实际上传入的是一个OkHttpCall<ResponseT>
CallAdapted(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,
Converter<ResponseBody, ResponseT> responseConverter,
CallAdapter<ResponseT, ReturnT> callAdapter) {
super(requestFactory, callFactory, responseConverter);
this.callAdapter = callAdapter;
}
// 将通用的响应类型Call<ResponseT> call,转化为接口方法具体的ReturnT,就是将OkHttpCall<ResponseT> ==> ReturnT
@Override protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
return callAdapter.adapt(call);
}
}
在前面讲到接口生成的动态代理类,调用接口方法时实际上调用到InvocationHandler的invoke方法,最终拿到的返回结果是
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
先看调用loadServiceMethod最终返回的CallAdapted类,这也是一个HttpServiceMethod类型,最终调用了HttpServiceMethod的invoke方法,
@Override final @Nullable ReturnT invoke(Object[] args) {
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);
}
这里调用了adapt方法,而其中又调用了callAdapter.adapt(call);,callAdapter又来自于createCallAdapter方法。
CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method, adapterType, annotations);
最终调用到Retrofit中的nextCallAdapter方法。
public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
Annotation[] annotations) {
......
int start = callAdapterFactories.indexOf(skipPast) + 1;
for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
// 从工厂缓存中找到对应类型工厂,生成callAdapter
CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
........
}
5.CallAdapter<R, T>
上面的代码中看到有个createCallAdapter的过程,而CallAdapter<R, T>是具体作用什么什么呢?回忆下接口定义。
@GET("/repos/{owner}/{repo}/contributors")
Call<List<Contributor>> contributors(
@Path("owner") String owner,
@Path("repo") String repo);
这里的contributors方法返回的响应数据是包含在Call中的,定义框架在接收到响应后,需要将其转换为我们想要的格式,当前接口我们用的就是Call实际上没有做转换。其作用就是将上游的Call ==> T 。
这里又个很重要的地方就是先明确,Call 是returnType,而尖括号里面的是responseType。
下面看下这个结果转化接口的具体实现。
// 将Call<Responsetype> 转化为 ReturnT,这个CallAdapter由Factory创建。
// 而Factory可以通过Retrofit.Builder#addCallAdapterFactory(Factory)添加进来
public interface CallAdapter<R, T> {
// 获取ResponseType类型,
Type responseType();
// 转化Call为RetrunT类型,
T adapt(Call<R> call);
// 创建Adapter的工厂
abstract class Factory {
// 返回一个可以被该工厂处理的Adapter,如果不能处理则返回null
public abstract @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations,
Retrofit retrofit);
// 提取范型实例的上边界类型,index 是代表第几个范型实例参数。
// 入参是1,Map<String,? extends Runnable> , 返回结果为Runnable类型。
protected static Type getParameterUpperBound(int index, ParameterizedType type) {
return Utils.getParameterUpperBound(index, type);
}
// 获取传入Type的字节码对象,
protected static Class<?> getRawType(Type type) {
return Utils.getRawType(type);
}
}
}
6.DefaultCallAdapterFactory
查看下Retrofit的构建过程,是通过建造者模式创建,在其Builder中可以找到如下代码:
// Make a defensive copy of the adapters and add the default Call adapter.
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
可见在默认情况下使用的是平台默认的callAdapterFactory,此处以Android平台为例
@Override List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
@Nullable Executor callbackExecutor) {
if (callbackExecutor == null) throw new AssertionError();
DefaultCallAdapterFactory executorFactory = new DefaultCallAdapterFactory(callbackExecutor);
return Build.VERSION.SDK_INT >= 24
? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
: singletonList(executorFactory);
}
可见默认情况下的callAdapterFactories在SDK版本>=24的情况下有两个工厂实例,之前的的版本只有DefaultCallAdapterFactory一个实例,下面继续看DefaultCallAdapterFactory的实现
final class DefaultCallAdapterFactory extends CallAdapter.Factory {
private final @Nullable Executor callbackExecutor;
.....................
// 只关心最终返回的CallAdapter,
return new CallAdapter<Object, Call<?>>() {
@Override public Type responseType() {
return responseType;
}
// 其实没有做转换,因为默认情况下executor为null, 所以返回的还是call。
@Override public Call<Object> adapt(Call<Object> call) {
return executor == null
? call
: new ExecutorCallbackCall<>(executor, call);// 设置了线程就切换个线程。
}
};
}
.....................
}
上面的工厂类返回了一个CallAdapter,实际上没有做什么结果上的转换,下面回忆一下第三章最开始的时候,使用生成的动态代理对象,我们拿到了Call类型的最终返回。
// Create a call instance for looking up Retrofit contributors.
Call<List<Contributor>> call = github.contributors("square", "retrofit");
实际使用中我们很多情况下是使用RxJava2来发射请求。下面看下R xJava 的结果适配器。
7.RxJava2CallAdapterFactory
可以通过静态方法创建同步工厂(当前线程),同步工厂(指定线程),异步工厂,
public final class RxJava2CallAdapterFactory extends CallAdapter.Factory {
// 创建一个运行在当前线程的同步的可观察对象
public static RxJava2CallAdapterFactory create() {
return new RxJava2CallAdapterFactory(null, false);
}
// 创建一个异步可观察者对象
public static RxJava2CallAdapterFactory createAsync() {
return new RxJava2CallAdapterFactory(null, true);
}
// 创建运行在指定线程的同步可观察者对象
@SuppressWarnings("ConstantConditions") // Guarding public API nullability.
public static RxJava2CallAdapterFactory createWithScheduler(Scheduler scheduler) {
if (scheduler == null) throw new NullPointerException("scheduler == null");
return new RxJava2CallAdapterFactory(scheduler, false);
}
private final @Nullable Scheduler scheduler;// 线程调度器
private final boolean isAsync;// 是否是同步
private RxJava2CallAdapterFactory(@Nullable Scheduler scheduler, boolean isAsync) {
this.scheduler = scheduler;
this.isAsync = isAsync;
}
@Override public @Nullable CallAdapter<?, ?> get(
Type returnType,
Annotation[] annotations,
Retrofit retrofit
) {
Class<?> rawType = getRawType(returnType);// 将拿到Type类型对应的Class
// 当返回类型为Completable时创建对应的CallAdapter
if (rawType == Completable.class) {
// Completable is not parameterized (which is what the rest of this method deals with) so it
// can only be created with a single configuration.
return new RxJava2CallAdapter(Void.class, scheduler, isAsync, false, true, false, false,
false, true);
}
// 判断是否为RxJava2CallAdapterFactory支持的其它类型,不是的话就直接返回为空。
boolean isFlowable = rawType == Flowable.class;
boolean isSingle = rawType == Single.class;
boolean isMaybe = rawType == Maybe.class;
if (rawType != Observable.class && !isFlowable && !isSingle && !isMaybe) {
return null;
}
boolean isResult = false;// 非Observable<Response<User>>类型
boolean isBody = false;//非Observable<Result<User>>类型
Type responseType;
//要求返回值类型必须是参数化的范型,即范型实例。Collection<String> 明确指定范型的类型或者边界。
if (!(returnType instanceof ParameterizedType)) {
String name = isFlowable ? "Flowable"
: isSingle ? "Single"
: isMaybe ? "Maybe" : "Observable";
throw new IllegalStateException(name + " return type must be parameterized"
+ " as " + name + "<Foo> or " + name + "<? extends Foo>");
}
// 获取ResponseType类型的上边界,比如<? extends Foo> 就返回Foo 类型。
Type observableType = getParameterUpperBound(0, (ParameterizedType) returnType);
// 拿到Class类型。
Class<?> rawObservableType = getRawType(observableType);
// 判断是否是 Observable<Response<User>>这种情况,如果是的话还需要判断Response范型实例内部是否是范型实例。
if (rawObservableType == Response.class) {
if (!(observableType instanceof ParameterizedType)) {
throw new IllegalStateException("Response must be parameterized"
+ " as Response<Foo> or Response<? extends Foo>");
}// 是的话就获取实际返回值类型,只获取第一个范型实参。
responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
// 判断是否是Observable<Result<User>>这种情况,同样需要判断Result内部的类型是否是范型实例。
} else if (rawObservableType == Result.class) {
if (!(observableType instanceof ParameterizedType)) {
throw new IllegalStateException("Result must be parameterized"
+ " as Result<Foo> or Result<? extends Foo>");
}
responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
isResult = true;
} else {
responseType = observableType;
isBody = true;// 标记为直接body,
}
return new RxJava2CallAdapter(responseType, scheduler, isAsync, isResult, isBody, isFlowable,
isSingle, isMaybe, false);
}
}
(1)使用RxJava2创建一个可观察工厂,支持Observable、Flowable、Single、Completable、Maybe等类型,
(2)Observable 直接包含结果,在2XX响应码下会调用onNext,其他情况调用onError。
(3)Observable<Response> 使用Responses包装结果,在底层http响应都正常时调用onNext,在IO异常时调用onError。
(4)Observable<Result> 使用Result包装,则在任何响应和错误的情况下都会调用到onNext。
下面是RxJava2CallAdapter的具体实现,根据构造函数的参数,决定了最终的Observable。
final class RxJava2CallAdapter<R> implements CallAdapter<R, Object> {
// 省略构造函数及其成员变量
....
@Override public Type responseType() {
return responseType;
}
@Override public Object adapt(Call<R> call) {
Observable<Response<R>> responseObservable = isAsync
? new CallEnqueueObservable<>(call)
: new CallExecuteObservable<>(call);
Observable<?> observable;
if (isResult) { // 对应Observable<Result<User>>
observable = new ResultObservable<>(responseObservable);
} else if (isBody) {// 对应Observable<User>
observable = new BodyObservable<>(responseObservable);
} else {// 对应Observable<Response<User>>
observable = responseObservable;
}
// 省略isFlowable、isSingle、isCompletable等。
.....
return RxJavaPlugins.onAssembly(observable);
}
}
这里我们需要注意的是BodyObservable和ResultObservable,前面提到
bservable 直接包含结果,在2XX响应码下会调用onNext,其他情况调用onError。下面验证一下具体实现。
final class BodyObservable<T> extends Observable<T> {
......
private static class BodyObserver<R> implements Observer<Response<R>> {
private final Observer<? super R> observer;
.....
@Override public void onNext(Response<R> response) {
// 验证了code范围后就直接onNext了。
if (response.isSuccessful()) {// return this.code >= 200 && this.code < 300;
observer.onNext(response.body());
} else {
terminated = true;
Throwable t = new HttpException(response);
try {
observer.onError(t);
} catch (Throwable inner) {
Exceptions.throwIfFatal(inner);
RxJavaPlugins.onError(new CompositeException(t, inner));
}
}
}
......
}
}
}
8. Converter.Factory
上面的代码中将上游的ResponseBody 转化为ResponseT的过程中用到了ConverterFactory,这里Converter.Factory主要实现将自定义类型转换为RequestBody,或者将ResponseBody转化为自定义类型,具体代码如下:
jpublic interface Converter<F, T> {
@Nullable T convert(F value) throws IOException;
/** Creates {@link Converter} instances based on a type and target usage. */
abstract class Factory {
// 将ResponseBody转化为自定义类型
public @Nullable Converter<ResponseBody, ?> responseBodyConverter(Type type,
Annotation[] annotations, Retrofit retrofit) {
return null;
}
// 将自定义类型转化为RequestBody
public @Nullable Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
return null;
}
// 将自定义类型转化为String
public @Nullable Converter<?, String> stringConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
return null;
}
// 获取类型上边界。index 1 of {@code Map<String, ? extends Runnable>} returns {@code Runnable}.
protected static Type getParameterUpperBound(int index, ParameterizedType type) {
return Utils.getParameterUpperBound(index, type);
}
// 抽取原始类型the type representing{@code List<? extends Runnable>} returns {@code List.class}.
protected static Class<?> getRawType(Type type) {
return Utils.getRawType(type);
}
}
}
Converter是一个接口,这里我们举例看下常见实现OptionalConverter
@IgnoreJRERequirement // Only added when Optional is available (Java 8+ / Android API 24+).
final class OptionalConverterFactory extends Converter.Factory {
static final Converter.Factory INSTANCE = new OptionalConverterFactory();
// 覆写responseBodyConverter方法,
@Override public @Nullable Converter<ResponseBody, ?> responseBodyConverter(
Type type, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(type) != Optional.class) {
return null;
}
Type innerType = getParameterUpperBound(0, (ParameterizedType) type);
Converter<ResponseBody, Object> delegate =
retrofit.responseBodyConverter(innerType, annotations);
return new OptionalConverter<>(delegate);
}
@IgnoreJRERequirement
static final class OptionalConverter<T> implements Converter<ResponseBody, Optional<T>> {
final Converter<ResponseBody, T> delegate;
OptionalConverter(Converter<ResponseBody, T> delegate) {
this.delegate = delegate;
}
// 接口中只需要实现convert即可。
@Override public Optional<T> convert(ResponseBody value) throws IOException {
return Optional.ofNullable(delegate.convert(value));
}
}
}
9.GsonConverterFactory
converter用做类型转换,Retrofit 发射请求需要RequestBody,converter就是将我们传入的参数对象转换为字节字符串。或者从RespondBody的字节流中反序列化为对象实例。
public final class GsonConverterFactory extends Converter.Factory {
// 创建Factory实例
public static GsonConverterFactory create() {
return create(new Gson());
}
// 创建Factory实例
@SuppressWarnings("ConstantConditions") // Guarding public API nullability.
public static GsonConverterFactory create(Gson gson) {
if (gson == null) throw new NullPointerException("gson == null");
return new GsonConverterFactory(gson);
}
private final Gson gson;
private GsonConverterFactory(Gson gson) {
this.gson = gson;
}
// 根据传入的要适配的type,在Gson中找到对应的TypeAdapter,然后创建GsonResponseBodyConverter
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
// 查找合适的转换器
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonResponseBodyConverter<>(gson, adapter);
}
// 同理根据传入的要适配的type,在Gson中查找对应的TypeAdapter,
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonRequestBodyConverter<>(gson, adapter);
}
}
此处的TypeAdapter就是执行着类型转换的工作,Gson 默认支持多种类型,但针对我们自定义的对象,Gson通常是使用的是ReflectiveTypeAdapterFactory 这个工厂类创建的Adapter。下面看下这个工厂如何创建合适的Adapter。
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
// 首先要拿到type的原始类型,查看是否是Object类型。
Class<? super T> raw = type.getRawType();
if (!Object.class.isAssignableFrom(raw)) {
return null;
} else {
//如果是Object类型则寻找对应的对象构造器。
ObjectConstructor<T> constructor = this.constructorConstructor.get(type);
return new ReflectiveTypeAdapterFactory.Adapter(constructor, this.getBoundFields(gson, type, raw));
}
}
下面看下constructorConstructor.get(type)的执行过程。
public <T> ObjectConstructor<T> get(TypeToken<T> typeToken) {
final Type type = typeToken.getType();// 获取转化类型
Class<? super T> rawType = typeToken.getRawType();
final InstanceCreator<T> typeCreator = (InstanceCreator)this.instanceCreators.get(type);
// 1.判断是否有对应的typeCreator
if (typeCreator != null) {
// 如果存在则创建一个ObjectConstructor匿名内部类对象,最终还是依赖typeCreator来创建具体实例对象
return new ObjectConstructor<T>() {
public T construct() {
return typeCreator.createInstance(type);
}
};
} else {
//2.没有则查找是否有原始类型对应的rawTypeCreator
final InstanceCreator<T> rawTypeCreator = (InstanceCreator)this.instanceCreators.get(rawType);
if (rawTypeCreator != null) {
return new ObjectConstructor<T>() {
public T construct() {
return rawTypeCreator.createInstance(type);
}
};
} else {
// 3.如果都没有则尝试调用默认无参构造函数来生成实例对象
ObjectConstructor<T> defaultConstructor = this.newDefaultConstructor(rawType);
if (defaultConstructor != null) {
return defaultConstructor;
} else {
// 4. 如果连无参构造函数都没有,那就判断是否是范型类型,根据类型来创建实例对象。
ObjectConstructor<T> defaultImplementation = this.newDefaultImplementationConstructor(type, rawType);
//5. 如果还是无法构造对象,那就使用大杀器了,
return defaultImplementation != null ? defaultImplementation : this.newUnsafeAllocator(type, rawType);
}
}
}
}
在UnsafeAllocator中,使用反射调用Unsafe类的allocateInstance方法,不考虑构造函数了,直接在内存上开辟一块区域,创建一个实例对象。
public static UnsafeAllocator create() {
try {
Class<?> unsafeClass = Class.forName("sun.misc.Unsafe");
Field f = unsafeClass.getDeclaredField("theUnsafe");
f.setAccessible(true);
final Object unsafe = f.get((Object)null);
final Method allocateInstance = unsafeClass.getMethod("allocateInstance", Class.class);
return new UnsafeAllocator() {
public <T> T newInstance(Class<T> c) throws Exception {
assertInstantiable(c);
return allocateInstance.invoke(unsafe, c);
}
};
} catch (Exception var6) {
......
10.GsonRequestBodyConverter
final class GsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
private static final MediaType MEDIA_TYPE = MediaType.get("application/json; charset=UTF-8");
private static final Charset UTF_8 = Charset.forName("UTF-8");
private final Gson gson;
private final TypeAdapter<T> adapter;
GsonRequestBodyConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson = gson;
this.adapter = adapter;
}
@Override public RequestBody convert(T value) throws IOException {
Buffer buffer = new Buffer();
Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);
JsonWriter jsonWriter = gson.newJsonWriter(writer);
adapter.write(jsonWriter, value);
jsonWriter.close();
return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
}
}
11.GsonRequestBodyConverter
final class GsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
private static final MediaType MEDIA_TYPE = MediaType.get("application/json; charset=UTF-8");
private static final Charset UTF_8 = Charset.forName("UTF-8");
private final Gson gson;
private final TypeAdapter<T> adapter;
GsonRequestBodyConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson = gson;
this.adapter = adapter;
}
@Override public RequestBody convert(T value) throws IOException {
Buffer buffer = new Buffer();
Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);
JsonWriter jsonWriter = gson.newJsonWriter(writer);
adapter.write(jsonWriter, value);
jsonWriter.close();
return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
}
}
引用:
https://square.github.io/retrofit/
https://www.cnblogs.com/liuyun1995/p/8144676.html
https://blog.csdn.net/flyfeifei66/article/details/81481222
Key promoter插件——快捷键显示提示