netty5笔记-总体流程分析3-ChannelHandlerContext
Netty4学习笔记(1)— ChannelPipeline
处理链处理写操作流程、Pipeline,Context和Handler的协作处理。
netty核心的概念:Channel、Buffer、Selecter
Channel
Channel是核心的一个接口,表示一个联络Socket的通道。通过Channel,可以对Socket进行各种操作。
ChannelHandler
在实际程序实现中,很少直接操作Channel,而是通过ChannelHandler来间接操纵Channel。(使用策略模式?)
ChannelHandler的种类:
ChannelHandler接口的子接口
- ChannelInboundHandler
- ChannelOutboundHandler
5.0.0.Alpha1 版本已经没有了这两个接口,why。4.1.5存在。
ChannelPipeline
ChannelPipeline里有一个双向链表,使用HashMap存放节点。节点类型为:ChannelHandlerContext。
是一个ChandlerHandler的链表。当需要对Channel进行某种处理的时候,Pipeline负责依次调用每一个Handler进行处理。(责任链模式?)
每个Channel都有一个属于自己的Pipeline.(一对一关系)
ChannelPipeline的方法有很多,其中一部分是用来管理ChannelHandler的,如下面这些:
1 2 3 4 5 6 7 8 9 10 11 12 13
| ChannelPipeline addFirst(String name, ChannelHandler handler); ChannelPipeline addLast(String name, ChannelHandler handler); ChannelPipeline addBefore(String baseName, String name, ChannelHandler handler); ChannelPipeline addAfter(String baseName, String name, ChannelHandler handler); ChannelPipeline remove(ChannelHandler handler); ChannelHandler remove(String name); ChannelHandler removeFirst(); ChannelHandler removeLast(); ChannelPipeline replace(ChannelHandler oldHandler, String newName, ChannelHandler newHandler); ChannelHandler replace(String oldName, String newName, ChannelHandler newHandler); ChannelHandler first(); ChannelHandler last(); ChannelHandler get(String name);
|
事件的传播
为了搞清楚事件如何在Pipeline里传播,
- 让我们从Channel的抽象子类AbstractChannel开始:
1 2 3 4 5 6 7 8
| public abstract class AbstractChannel extends DefaultAttributeMap implements Channel { // ... @Override public Channel write(Object msg) { return pipeline.write(msg); } // ... }
|
- 再看DefaultChannelPipeline的write()方法实现
1 2 3 4 5 6 7 8
| final class DefaultChannelPipeline implements ChannelPipeline { // ... @Override public ChannelFuture write(Object msg) { return tail.write(msg); } // ... }
|
因为write是个outbound事件,所以DefaultChannelPipeline直接找到tail部分的context,调用其write()方法
- 接着看DefaultChannelHandlerContext的write()方法
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 44 45 46
| final class DefaultChannelHandlerContext extends DefaultAttributeMap implements ChannelHandlerContext { // ... @Override public ChannelFuture write(Object msg) { return write(msg, newPromise()); } @Override public ChannelFuture write(final Object msg, final ChannelPromise promise) { if (msg == null) { throw new NullPointerException("msg"); } validatePromise(promise, true); write(msg, false, promise); return promise; } private void write(Object msg, boolean flush, ChannelPromise promise) { DefaultChannelHandlerContext next = findContextOutbound(); next.invokeWrite(msg, promise); if (flush) { next.invokeFlush(); } } private DefaultChannelHandlerContext findContextOutbound() { DefaultChannelHandlerContext ctx = this; do { ctx = ctx.prev; } while (!ctx.outbound); return ctx; } private void invokeWrite(Object msg, ChannelPromise promise) { try { ((ChannelOutboundHandler) handler).write(this, msg, promise); } catch (Throwable t) { notifyOutboundHandlerException(t, promise); } } // ... }
|
context的write()方法沿着context链往前找,直至找到一个outbound类型的context为止,然后调用其invokeWrite()方法
invokeWrite()接着调用handler的write()方法:
ChannelHandlerContext
ChannelPipeline并不是直接管理ChannelHandler,而是通过ChannelHandlerContext来间接管理,这一点通过ChannelPipeline的默认实现DefaultChannelPipeline可以看出来。
调用ChannelHandlerContext#channel()方法可以得到和Context绑定的Channel,调用ChannelHandlerContext#handler()方法可以得到和Context绑定的Handler。
一个ChannelHandlerContext只能对应一个ChannelHander,只对应一个Channel,而一个ChannelHander则可以对应多个ChannelHandlerContext