0%

SourceAnalysis-Netty-ChannelHandlerContext

阅读更多

1 前言

本篇博文以DefaultChannelHandlerContext为例对ChannelHandler的结构进行分析

2 继承结构

DefaultChannelHandlerContext

2.1 ChannelOutboundInvoker

ChannelOutboundInvoker接口定义了与ChannelOutboundHandler相似的方法

ChannelOutboundInvoker

2.2 ChannelInboundInvoker

ChannelInboundInvoker接口定义了与ChannelInboundHandler相似的方法

ChannelInboundInvoker

2.3 AttributeMap

AttributeMap接口定义了一种用于添加关键字以及判断关键字是否存在的Map

AttributeMap

2.4 DefaultAttributeMap

DefaultAttributeMap抽象类对AttributeMap接口提供了基本的实现

DefaultAttributeMap

2.5 ChannelHandlerContext

该接口作为Handler的上下文,继承自ChannelOutboundInvoker以及ChannelInboundInvoker接口,于是包含了触发这些Handler特定方法的方法

此外,ChannelHandlerContext作为Handler的上下文

  1. 与Channel一一对应
  2. 与EventExecutor一一对应
  3. 与Handler一一对应
  4. 与Pipeline一一对应

ChannelHandlerContext

3 AbstractChannelHandlerContext

AbstractChannelHandlerContext抽象类为ChannelHandlerContext接口提供了基础实现

AbstractChannelHandlerContext

AbstractChannelHandlerContext包含如下重要字段

  1. boolean inbound:用于标记当前持有的Handler是否为ChannelInbondHandler
  2. boolean outbound:用于标记当前持有的Handler是否为ChannelOutnbondHandler
  3. DefaultChannelPipeline pipeline:关联的DefaultChannelPipeline
  4. boolean ordered:关联的executor是否是OrderedEventExecutor
  5. EventExecutor executor:关联的EventExecutor,用于执行所有的异步任务

fireChannelRead为例,分析一下Handler特定生命周期如何被触发,以及在同一个生命周期中,调用过程如何在各个ChannelHandlerContext之间的传递

  1. 首先调用findContextInbound()方法,从当前位置开始(当前ChannelHandlerContext位于双向链表中的位置)向后寻找下一个Inbond类型的ChannelHandlerContext
  2. 通过静态方法invokeChannelRead触发ChannelRead方法
  3. 同步或者异步方式触发指定ChannelHandlerContext的channelRead方法
  4. 如果在该Handler的channelRead方法中包含ctx.channelRead(ctx,msg),那么该条执行链路就会沿着双向链表向后传递
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public ChannelHandlerContext fireChannelRead(final Object msg) {
//沿着双向链表的当前位置向后找到第一个Inbound类型的ChannelHandlerContext
invokeChannelRead(findContextInbound(), msg);
return this;
}

private AbstractChannelHandlerContext findContextInbound() {
AbstractChannelHandlerContext ctx = this;
do {
ctx = ctx.next;
} while (!ctx.inbound);
return ctx;
}

static void invokeChannelRead(final AbstractChannelHandlerContext next, Object msg) {
final Object m = next.pipeline.touch(ObjectUtil.checkNotNull(msg, "msg"), next);
EventExecutor executor = next.executor();
if (executor.inEventLoop()) {
//通过ChannelHandlerContext触发ChannelRead方法
next.invokeChannelRead(m);
} else {
executor.execute(new Runnable() {
@Override
public void run() {
//通过ChannelHandlerContext触发ChannelRead方法
next.invokeChannelRead(m);
}
});
}
}

private void invokeChannelRead(Object msg) {
if (invokeHandler()) {
try {
//重定向为Handler的channelRead方法
((ChannelInboundHandler) handler()).channelRead(this, msg);
} catch (Throwable t) {
notifyHandlerException(t);
}
} else {
fireChannelRead(msg);
}
}

4 DefaultChannelHandlerContext

DefaultChannelHandlerContext包含如下重要字段

  1. ChannelHandler handler:持有的Handler