前言
前段时间我们分析了kotlin的委托,委托实际上有点类似于静态代理模式,趁着委托的记忆还没有消失(我的记忆力比鱼稍微好一丢丢(理直气壮)),我们来分析下代理模式。
静态代理
静态代理模式中,有3个重要的角色
- 协议,它抽离了代理类和真实类的共性;
- 代理类,直接与客户进行交互,在内部访问真实类,但同时又可以对真实类的访问附加额外的操作;
- 真实类,代理类中真正操作的。
协议
首先我们定义一个抽象接口,它有一个request方法。1
2
3interface IBase{
fun request()
}
真实类
然后,我们定义一个真实类,它实现了协议。1
2
3
4
5class BaseImpl:IBase{
override fun request(){
//...request
}
}
代理类
最后,我们定义一个代理类,它同样也实现了协议,同时它包含了一个真实类的实例对象。1
2
3
4
5
6
7
8
9
10class BaseImplProxy:IBase{
private val baseImpl:BaseImpl by lazy{
BaseImpl()
}
override fun request(){
//这里实际调用真实角色的request()
baseImpl.request()
}
}
写到这里,我们发现上面和kotlin的委托是一模一样的原理。但是静态代理中,我们可以在request()中做一些额外的操作。1
2
3
4
5
6
7
8
9
10
11
12
13override fun request(){
preRequest()
baseImpl.request()
postRequest()
}
private fun preRequest(){
//...请求前做的事情
}
private fun postRequest(){
//...请求后做的事情
}
kotlin的委托就不能做这些事情。
动态代理
Java中的动态代理,我们得认识两个玩意,一个是InvocationHandler,一个是Proxy,它们位于reflect包下面。
协议
动态代理中,我们同样需要定义协议。1
2
3interface IBase{
fun request()
}
真实类
然后我们定义一个真实类。1
2
3
4class BaseImpl : IBase{
override fun request(){
}
}
实现InvocationHandler
然后我们需要实现InvocationHandler接口,里面包含有一个BaseImpl的实例对象。1
2
3
4
5
6
7
8
9
10
11class InvocationHandlerImpl : InvocationHandler {
private val baseImpl:BaseImpl by lazy{
BaseImpl()
}
override fun invoke(proxy: Any?, method: Method?, args: Array<out Any>?): Any? {
return method?.invoke(baseImpl, args)
}
}
创建代理类
一般我们会通过Proxy.newProxyInstance()创建代理类,它接受ClassLoader, Class<?>[]和一个InvocationHandler。1
2val clazz = IBaseImpl::class.java
val iBase:IBase = Proxy.newProxyInstance(clazz.classLoader, clazz.interfaces, object: InvocationHandlerImpl(){}) as IBase
这样我们通过iBase对象调用request()的时候实际上会被回调到InvocationHandler的invoke(),而我们在invoke()中调用了BaseImpl的request()。
Retrofit的动态代理
我们知道Retrofit里面使用了动态代理模式的。我们可以翻看它的源码,在Retrofit.java文件的create()中我们可以看到有动态代理的调用。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22public <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();
public Object invoke(Object proxy, Method method, Object... args) throws Throwable {
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);
}
});
}
比如我们定义如下一个接口请求。1
2
3
4
5
6
7
8interface AdsService {
fun fetchAdsInfo(
AdsReqBean reqBean:
): Single<Response<BaseRespBean<AdsRespBean>>>
}
然后通过Retrofit的create()方法,我们就可以得到一个AdsService的代理对象了。