上篇文章简单理解责任链模式只做了Demo,这篇文章就结合OKHttp的框架来具体看看责任链模式,没看过上篇文章的建议可以看看,尤其是第四点优化代码那一块。
一个框架中往往会涉及到很多的设计模式,在OKHttp中用到责任链模式的是拦截器Interceptor,因为只是对责任链模式的源码分析,所有我会省略掉那些影响我们看源码的部分。
一、OkHttp框架中的Interceptor是如何使用责任链模式的
1、OKHttp的一个简单应用入口
@Test
public void test(){
try{
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("http://www.baidu.com/")
.build();
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
System.out.println(response.body().string());
}catch (Exception e){
}
}
2、关键性源码分析
client.newCall(request),实例化了一个RealCall
@Override public Call newCall(Request request) {
return new RealCall(this, request, false /* for web socket */);
}
client.newCall(request).execute() ,直接看RealCall中的execute()方法
@Override public Response execute() throws IOException {
...
Response result = getResponseWithInterceptorChain();
...
getResponseWithInterceptorChain(),执行拦截器
- 责任链模式的Client
Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
List<Interceptor> interceptors = new ArrayList<>();
//第一步:把对应的五个拦截器都放入到interceptors List中
interceptors.addAll(client.interceptors());
interceptors.add(retryAndFollowUpInterceptor);
interceptors.add(new BridgeInterceptor(client.cookieJar()));
interceptors.add(new CacheInterceptor(client.internalCache()));
interceptors.add(new ConnectInterceptor(client));
if (!forWebSocket) {
interceptors.addAll(client.networkInterceptors());
}
interceptors.add(new CallServerInterceptor(forWebSocket));
//第二步:把所有的具体处理者链接起来
Interceptor.Chain chain = new RealInterceptorChain(
interceptors, null, null, null, 0, originalRequest);
//第三步:开始处理
return chain.proceed(originalRequest);
}
上面的代码和下面的这个截图是不是一样的(有不懂的童鞋,请看上篇简单理解责任链模式)
- 真实的链接类
public final class RealInterceptorChain implements Interceptor.Chain {
private final List<Interceptor> interceptors;
private final int index;
...
public RealInterceptorChain(List<Interceptor> interceptors, int index) {
this.interceptors = interceptors;
this.index = index;
}
public Response proceed(...) {
if (index >= interceptors.size()) throw new AssertionError();
...
// Call the next interceptor in the chain.
RealInterceptorChain next = new RealInterceptorChain(
interceptors, index + 1);
Interceptor interceptor = interceptors.get(index);
Response response = interceptor.intercept(next);
....
return response;
}
}
源码中index的值是从构造方法中传入的,追溯上去,可以看到初始化的index值传入的是0
- 具体的处理者(有5个)
public final class RetryAndFollowUpInterceptor implements Interceptor {
......
@Override
public Response intercept(Chain chain) {
....
response = ((RealInterceptorChain) chain).proceed(request, streamAllocation, null, null);
.....
}
}
public final class BridgeInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
......
Response networkResponse = chain.proceed(requestBuilder.build());
.......
}
}
public final class CacheInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
......
networkResponse = chain.proceed(networkRequest);
.......
}
}
public final class ConnectInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
RealInterceptorChain realChain = (RealInterceptorChain) chain;
...
return realChain.proceed(request, streamAllocation, httpCodec, connection);
}
}
/** This is the last interceptor in the chain. It makes a network call to the server. */
public final class CallServerInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
.....
//类上有注释,这是链上的最后一个拦截器,所以就没调用proceed()了
}
}
对比下,下面是简单的一个demo,上面是实际项目中的应用
- 抽象处理者
public interface Interceptor {
Response intercept(Chain chain) throws IOException;
interface Chain {
Request request();
//链头的具体处理者
Response proceed(Request request) throws IOException;
Connection connection();
}
}
1)在责任链模式的概念中把抽象处理类都是定义成abstract类,在OKHttp的实际应用中我们看到是定义成interface的
2)demo和实际对比,发现实际中把链头的具体处理者定义成一个接口的,让RealInterceptorChain去实现这个接口
public final class RealInterceptorChain implements Interceptor.Chain {
@Override
public Response proceed(Request request) throws IOException {
return proceed(request, streamAllocation, httpCodec, connection);
}
public Response proceed(....) throws IOException {
// Call the next interceptor in the chain.
RealInterceptorChain next = new RealInterceptorChain(
interceptors, streamAllocation, httpCodec, connection, index + 1, request);
Interceptor interceptor = interceptors.get(index);
//这里调用抽象接口自己的抽象方法
Response response = interceptor.intercept(next);
return response;
}
}
3、OKHttp责任链模式的结构图
(第一次画这个图,折腾了好久,尤其是Interceptor和Chain之间的关系,我用了一个关联,不知道到底对不对,有问题的话,请帮忙指出,好修正,谢谢!)
3、OKHttp实现原理图
从参考文档中的博主哪儿借用一张原理图,懒得自己去画了