【netty源码之ChannelHandlerContext】

一、ChannelHandlerContext是什么?

ChannelHandlerContext代表了ChannelHandler和ChannelPipline之间的关联,每当有一个ChannelHandler添加到ChannelPipline中时,都会创建一个ChannelHandlerContext。主要功能是管理它所关联的ChannelHandler和在同一个ChannelPipline中的其他ChannelHandler之间的交互。
在这里插入图片描述

二、ChannelHandlerContext的API

在这里插入图片描述

1、channel()、pipeline()、handler()、alloc()、executor()

返回该ChannelHandlerContext绑定的各种组件。

2、fire类方法

触发对pipeline上下一个ChannelInBoundHandler上的对应方法的调用。

3、read()

将数据从Channel读取到第一个入站缓冲区;如果读取成功则触发一个channelRead事件,并在最后一个消息被读取完成后通知ChannelInBoundHandler的channelReadComplete(ctx)方法。

4、write()

通过该ctx写入消息。

三、骨架类AbstractChannelHandlerContext

在AbstractChannelHandlerContext类中实现了ChannelHandlerContext的绝大多数方法逻辑。

1、alloc()方法

在这里插入图片描述
通过pipeline获取channel,再获取到对应的ChannelConfig,调用DefaultChannelConfig的getAllocator()方法。
在这里插入图片描述

private volatile ByteBufAllocator allocator = ByteBufAllocator.DEFAULT;
ByteBufAllocator DEFAULT = ByteBufUtil.DEFAULT_ALLOCATOR;

在这里插入图片描述
可以看到,只有android是默认使用unpooled的,其他均使用pooled。

alloc = PooledByteBufAllocator.DEFAULT;
public static final PooledByteBufAllocator DEFAULT =
            new PooledByteBufAllocator(PlatformDependent.directBufferPreferred());

至此,我们看到默认的分配器是PooledByteBufAllocator。

2、read()方法

在这里插入图片描述
首先会寻找下一个出站处理器,然后取其线程调用其read方法。其实普通的ctx在read的时候就是做了一个传递,真正有执行逻辑的就是pipeline的最后一个出站处理器,也就是HeadContext。接第四节第1个方法描述。

3、write方法

在这里插入图片描述
注意到,在进行基础检验或者发生异常时,调用了ReferenceCountUtil.release(msg)方法进行内存释放。
在这里插入图片描述
接下来就如出一辙了,沿着出站处理器往下传递,直到最后一个HeadContext。
4、file类方法fireChannelRead()方法
在这里插入图片描述
找到下一个进站处理器,触发对应方法的调用。

四、实现类HeadContext

pipeline中的第一个ctx,既是入站处理器,也是出站处理器。

1、read()方法

在这里插入图片描述
调用了unsafe的beginRead方法。
在这里插入图片描述
这个unsafe是channel的unsafe。

在这里插入图片描述
该方法在AbstractChannel中实现。调用了钩子方法doBeginRead。我们进AbstractNioChannel类继续追踪
在这里插入图片描述
最终是给该channel在selector上注册了读事件。

2、write()方法

在这里插入图片描述
同样也是调用了unsafe的write方法。
在这里插入图片描述
可以看到是把数据写到了出站缓冲区中。

3、channelActive()方法

在这里插入图片描述
除了向后传递,还调用了readIfIsAutoRead()方法。
在这里插入图片描述
这个方法也很简单,调用了channel的read方法,最终调用了HeadContext的read方法,也就是本节介绍的第1个方法,为该channel注册了读事件。

五、实现类TailContext

pipeline中的最后一个ctx,入站处理器链的最后一个节点。

1、channelRead()方法

在这里插入图片描述
看到仅仅是调用了DefaultChannelPipline的onUnhandledInboundMessage()方法。
在这里插入图片描述
在这个方法中,只是打印了日志,并对内存进行了释放。这就告诉我们,在我们自定义实现的inBoundHandler中,只要我们调用file方法把msg传递下去,netty已经给我们做好了内存回收,不用担心内存泄露问题。

六、实现类DefaultChannelHandlerContext

在这里插入图片描述
可以看到在该类中并没有过多的方法实现,这也就是netty的设计思想,尽量在Abstract类中把该实现的都实现了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值