Netty的ChannelHandlerMask是用于标记ChannelHandler的位掩码。它被用于指示ChannelHandler的事件处理方式。ChannelHandlerMask 定义了ChannelHandler所有事件。
final class ChannelHandlerMask {
static final int MASK_EXCEPTION_CAUGHT = 1;
static final int MASK_CHANNEL_REGISTERED = 2;
static final int MASK_CHANNEL_UNREGISTERED = 4;
static final int MASK_CHANNEL_ACTIVE = 8;
static final int MASK_CHANNEL_INACTIVE = 16;
static final int MASK_CHANNEL_READ = 32;
static final int MASK_CHANNEL_READ_COMPLETE = 64;
static final int MASK_USER_EVENT_TRIGGERED = 128;
static final int MASK_CHANNEL_WRITABILITY_CHANGED = 256;
static final int MASK_BIND = 512;
static final int MASK_CONNECT = 1024;
static final int MASK_DISCONNECT = 2048;
static final int MASK_CLOSE = 4096;
static final int MASK_DEREGISTER = 8192;
static final int MASK_READ = 16384;
static final int MASK_WRITE = 32768;
static final int MASK_FLUSH = 65536;
private static final int MASK_ALL_INBOUND = 511;
private static final int MASK_ALL_OUTBOUND = 130561;
}
每个ChannelHandler对象都有一个位掩码,保存在对应的ChannelHandlerContext的io.netty.channel.AbstractChannelHandlerContext#executionMask字段,如图
AbstractChannelHandlerContext(DefaultChannelPipeline pipeline, EventExecutor executor, String name, Class<? extends ChannelHandler> handlerClass) {
this.name = (String)ObjectUtil.checkNotNull(name, "name");
this.pipeline = pipeline;
this.executor = executor;
this.executionMask = ChannelHandlerMask.mask(handlerClass);
this.ordered = executor == null || executor instanceof OrderedEventExecutor;
}
executionMask字段是一个int类型,int类型总共有32位。
ChannelInboundHandler将ChannelHandlerMask低位(从右至左)的第二位到第九位作为监听事件类型。也就是说,所有ChannelInboundHandler的子类,位掩码为 "00000000000000000000000111111111"。如果某个ChannelInboundHandler对某个Inbound事件的监听不感兴趣,那么只需将对应位的掩码置为0。例如io.netty.bootstrap.ServerBootstrap.ServerBootstrapAcceptor对channelRegistered事件不感兴趣,则对应方法加上@Skip注解(该注解只对Netty内部的channel包代码开放)
左上的圆圈区域表示ServerBootstrapAcceptor类对于channelRegistered事件不感兴趣,因为ChannelInboundHandlerAdapter的channelRegistered方法带有@Skip注解(见图右上方)。从图下方圆圈区域的表达式计算,我们可以知道,ChannelInboundHandler位掩码为“00000000000000000000000111111111”(数字511),表示默认监听所有inboud事件,channelRegistered事件掩码为“11111111111111111111111111111101”(数字-3),ServerBootstrapAcceptor不监听channelRegistered事件,则将两个二进制进行与运行,得到00000000000000000000000111111101。
这里为了便于观察,涉及到将一个int类型显示成二级制格式,用到了一个工具类
public class BinaryUtil {
public static String binaryString(int num) {
StringBuilder sb = new StringBuilder();
for (int i = 31; i >=0 ; i--) {
int s = (num >> i) & 1;
sb.append(s);
}
return sb.toString();
}
}
类似地,将ChannelOutboundHandler将int从右至左的第十位到第十七位置为1,表示默认监听所有outbound事件,二进制值为“00000000000000011111111000000001”。从二进制可以看出,outboundhandler默认不监听所有inboud事件,这样,channelpipeline在分发事件的时候,可以跳过很多不必要的处理。
AbstractChannelHandlerContext每次寻找下一个ChannelHandlerContext的时候,都是从DefaultChannelPipeline$HeadContext出发,传入事件所对应的掩码,不停的迭代,直到找到下一个不跳过事件的handlercontext。