Retrofit中使用到了很多设计模式,其核心的模式是代理模式,因为Retrofit 不是一个网络框架,而是一个对网络框架进行封装的工具,利用注解将请求的接口以java的接口形式展现,其请求的核心还是Okhttp,它的几个核心的功能:转换注解、解析请求的参数、请求、将请求的结果适配为我们想要的结果等重要功能都是在动态代理中完成的
代理模式
在java代码中,代理模式分为静态代理和动态代理
静态代理
代理类通过实现与目标对象相同的接口,并在类中维护一个代理对象,通过构造函数实例化目标对象,保存给代理对象,在接下来的执行中代理对象实现接口方法,在这个方法中拦截,添加或者移除要修改的功能
看代码
/**
* 共同的接口
*/
interface IProxyInterface {
fun method()
}
/**
* 目标对象
*/
class TargetObject : IProxyInterface {
override fun method() {
println("这里是我原本要进行的操作")
}
}
/**
* 代理类
*/
class ProxyHelper(var iProxyInterface: IProxyInterface) : IProxyInterface {
override fun method() {
//再次做拦截之前的操作
iProxyInterface.method()
//再次做拦截之后的操作
}
}
- 优点:能完成我们在开发中大的代码块或依赖中的模块功能的修改和扩展
- 缺点:自己写代理类 增加了类文件,并且在接口发生改变时,代理类也需要改变
动态代理
既然静态代理存在很明显的缺点,那看一下动态代理,当然动态代理不需要自己实现代理类
动态代理类我们实现java提供的InvocationHandler类来实现,
看代码
/**
* 动态代理类对象
*
*/
class DynamicProxyHandler(var any: Any) :InvocationHandler {
override fun invoke(proxy: Any, method: Method, args: Array<out Any>): Any {
//操作前
val result = method.invoke(proxy, args)
//操作后
return result
}
}
/**
*测试类
**/
object Main {
@JvmStatic
fun main(args: Array<String>) {
// ProxyHelper(TargetObject()).method()
val iProxyInterface = TargetObject()
val proxyInterface = Proxy.newProxyInstance(
IProxyInterface::class.java.classLoader,
arrayOf<Class<*>>(IProxyInterface::class.java), DynamicProxyHandler(iProxyInterface)
) as IProxyInterface
proxyInterface.method()
}
}
- Proxy.newProxyInstance三个参数的说明:
- ClassLoader :指定当前目标对象使用的类加载器,获取加载器的方法是固定的
- Class<?>[] interfaces:指定目标对象实现的接口的类型,使用泛型方式确认类型
- InvocationHandler:执行目标对象的方法时通过回调invoke 方法完成操作
- 优点:不需要手动实现代理类
- 缺点:代理对象不需要实现接口但是目标对象一定要实现接口,
Retrofit 使用的就是动态代理
@SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.
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, @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);
}
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.adapt(okHttpCall);
}
});
}