一. 代理
代理这个词很好理解,就像我们耳熟能详的代购一样,我们不直接和商家去购买商品,而是通过中间商帮我们去买,这里的中间商就类似于代理的角色,当然中间商肯定是要赚差价的,哈哈,java中的代理根据创建时机以及方式的不同,可以分为两种:静态代理和动态代理。
1.静态代理
静态代理在使用时,被代理对象和代理对象需要有共同的父类或者实现同一接口,举个栗子,随便创建个类,作为我们所说的被代理对象,创建一个专门用于打印的接口PrintInfoIter
,然后如上所述,创建Student
类实现它:
interface PrintInfoIter {
fun printInfo()
}
class Student :PrintInfoIter{
override fun printInfo(){
Log.e("proxy","----printInfo")
}
}
然后创建代理对象类,同样需要实现PrintInfoIter
接口,如下:
class StudentImpProxy(var infoIter: PrintInfoIter) : PrintInfoIter {
private var printInfoIter: PrintInfoIter? = null
init {
this.printInfoIter = infoIter
}
override fun printInfo() {
printInfoIter?.let {
Log.e("proxy", "--------调用printInfo之前")
it.printInfo()
Log.e("proxy", "--------调用printInfo之后")
}
}
}
使用方式如下:
//静态代理
val studentImpProxy = StudentImpProxy(Student())
studentImpProxy.printInfo()
结果:
静态代理的作用就是在不修改被代理类代码的前提下,对功能进行扩展,缺点也很明显,需要代理类和被代理类都有共同的父类或者实现同一接口,之所以成为静态,个人理解是代码在程序运行之前已经编写完成,非动态生成实现代理功能。
2.动态代理
动态代理主要依赖Proxy
和InvocationHandler
来完成代理工作,通过Proxy的newProxyInstance方法来创建代理类:
//loader:类加载器
//interfaces:对象实现的所有接口数组
//h:InvocationHandler对象实例
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
如何使用呢?还是上面的栗子,看看使用动态代理的方式如何使用:
/**
* 动态代理类
*/
class StudentProxy : InvocationHandler {
var obj: Any? = null
fun newProxyInstance(obj: Any?): Any {
this.obj = obj
return Proxy.newProxyInstance(obj!!.javaClass.classLoader, obj.javaClass.interfaces, this)
}
override fun invoke(proxy: Any?, method: Method?, args: Array<out Any>?): Any {
var result: Any? = null
Log.e("proxy","--------调用${method}之前")
var argsTemp: Array<out Any>? = arrayOf()
args?.let {
if(args.isNotEmpty())
argsTemp = args
}
result = if(!argsTemp.isNullOrEmpty()){
method?.invoke(obj,argsTemp)
}else{
method?.invoke(obj )
}
Log.e("proxy","--------调用${method}之后")
return result ?: Any()
}
}
使用:
//动态代理
val studentProxy = StudentProxy()
val printInfoIter = studentProxy.newProxyInstance(Student()) as PrintInfoIter
printInfoIter.printInfo()
结果:
可以发现,动态代理不需要与被代理对象一样,实现相同接口或者共同父类,相对来说比较灵活,但它同样是基于接口进行代理,另外JDK动态代理是Java原生支持的,不需要任何外部依赖。
二.Retrofit
Retrofit
作为现在android
开发的主流网络框架,或者说是一个封装了网络请求各个环节的库,因为其底层依然是使用的okhttp
来发送网络请求,下面我们跟随源码来体验下其请求流程。
1.retrofit.create
我们在使用Retrofit
进行网络请求的时候,通常会需要一个配置接口参数的类,包看请求类型,参数,header等等,然后通过retrofit.create
获取该类实例,形如:
val apiService = retrofit.create(apiClass)
我们来看下retrofit.create
具体干了啥:
public <T> T create(final Class<T> service) {
validateServiceInterface(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);
}
});
}
Proxy.newProxyInstance
是不是很熟悉,上面刚介绍过,这边创建service类采用的就是动态代理的方式,主要代码就是loadServiceMethod(method).invoke
,loadServiceMethod是解析请求各种参数的类,下面我们具体来看下。
2.ServiceMethod
loadServiceMethod
是ServiceMethod
类型,代码如下:
ServiceMethod<?> loadServiceMethod(Method method) {
ServiceMethod<?> result = serviceMethodCache.get(method);
if (result != null) return result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
result = ServiceMethod.parseAnnotations(this, method);
serviceMethodCache.put(method, result);
}
}
return result;
}
ServiceMethod
是一个抽象类,具体实现类是HttpServiceMethod
,来看下它的parseAnnotations
方法:
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;
//Kotlin suspend的处理
if (isKotlinSuspendFunction) {
Type[] parameterTypes = method.getGenericParameterTypes();
Type responseType = Utils.getParameterLowerBound(0,
(ParameterizedType) parameterTypes[parameterTypes.length - 1]);
adapterType = new Utils.ParameterizedTypeImpl(null, Call.class, responseType);
annotations = SkipCallbackExecutorImpl.ensurePresent(annotations);
} else {
adapterType = method.getGenericReturnType();
}
//根据设置的addCallAdapterFactory类型,创建不同的callAdapter
CallAdapter<ResponseT, ReturnT> callAdapter =
createCallAdapter(retrofit, method, adapterType, annotations);
Type responseType = callAdapter.responseType();
//根据设置的addConverterFactory类型,创建不同的response转换器,用于把返回值装换为具体的实体类
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);
okhttp3.Call.Factory callFactory = retrofit.callFactory;
//不同情况创建不同的HttpServiceMethod
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);
}
}
这里创建了callAdapter
对象,通过calladapter
转换器,将okhttp3.call
转换成可以用于发起网络请求的retrofit2.Call
或者说用于rxjava
的Observable
对象,calladapter
对象可以通过addCallAdapterFactory
方法设置,不设置则使用系统默认的DefaultCallAdapterFactory
,比如我们如果使用rxjava
,通常会设置了RxJava2CallAdapter
,来看下RxJava2CallAdapter
的代码:
//这里只贴出关键代码
final class RxJava2CallAdapter<R> implements CallAdapter<R, Object> {
private final Type responseType;
private final @Nullable Scheduler scheduler;
private final boolean isAsync;
private final boolean isResult;
private final boolean isBody;
private final boolean isFlowable;
private final boolean isSingle;
private final boolean isMaybe;
private final boolean isCompletable;
RxJava2CallAdapter(Type responseType, @Nullable Scheduler scheduler, boolean isAsync,
boolean isResult, boolean isBody, boolean isFlowable, boolean isSingle, boolean isMaybe,
boolean isCompletable) {
this.responseType = responseType;
this.scheduler = scheduler;
......
}
@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 = new ResultObservable<>(responseObservable);
} else if (isBody) {
observable = new BodyObservable<>(responseObservable);
} else {
observable = responseObservable;
}
return RxJavaPlugins.onAssembly(observable);
}
}
可以看到RxJava2CallAdapter实现了Retrofit的CallAdapter接口,adapt方法中看到了两个熟悉的类CallEnqueueObservable和CallExecuteObservable,异步和同步网络请求的类,CallEnqueueObservable代码:
//只贴关键代码
final class CallEnqueueObservable<T> extends Observable<Response<T>> {
private final Call<T> originalCall;
CallEnqueueObservable(Call<T> originalCall) {
this.originalCall = originalCall;
}
@Override protected void subscribeActual(Observer<? super Response<T>> observer) {
// Since Call is a one-shot type, clone it for each new observer.
Call<T> call = originalCall.clone();
CallCallback<T> callback = new CallCallback<>(call, observer);
observer.onSubscribe(callback);
if (!callback.isDisposed()) {
//发送网络请求
call.enqueue(callback);
}
}
private static final class CallCallback<T> implements Disposable, Callback<T> {
private final Call<?> call;
private final Observer<? super Response<T>> observer;
private volatile boolean disposed;
boolean terminated = false;
CallCallback(Call<?> call, Observer<? super Response<T>> observer) {
this.call = call;
this.observer = observer;
}
@Override public void onResponse(Call<T> call, Response<T> response) {
if (disposed) return;
try {
observer.onNext(response);
if (!disposed) {
terminated = true;
observer.onComplete();
}
} catch (Throwable t) {
}
}
@Override public void onFailure(Call<T> call, Throwable t) {
}
@Override public void dispose() {
call.cancel();
}
}
}
这里通过call.enqueue
发送网络请求,call
其实就是HttpServiceMethod
类中invoke
方法中所创建的OkHttpCall
,OkHttpCall
是对okhttp
网络请求的封装,也是Retrofit
中具体发送网络请求的类:
@Override final @Nullable ReturnT invoke(Object[] args) {
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);
}
3.OkHttpCall
OkHttpCall
是retrofit
库对okhttp
网络请求的封装,可以简单看下OkHttpCall
中的方法,发现都是okhttp
中耳熟能详的内容,比如enqueue,execute
等:
网络请求流程:在调用apiService方法时,Retrofit的create()通过动态代理生成一个代理类对象,也就是通过Proxy.newProxyInstance()来创建的代理对象,接下来使用ServiceMethod类解析各种注解,封装请求,之后调用invoke()方法,创建用于发送网络请求的okhttpcall类,最终返回用于发起网络请求的Call对象或者用于结合rxjava使用的Observable对象。
简单来讲,其实retrofit网络框架就是对okhttp网络框架的封装,可以更加方便的发起网络请求,简单几步即可完成,另外可以比较好的搭配rxjava或者kotlin协程,使得网络请求变得方便快捷,至此,本文所要介绍的内容已接近尾声,如果对你有任何帮助,点赞支持下我会非常开心!