/** * ChannelHandlerContext 实现了ChannelInboundInvoker和ChannelOutboundInvoker * * ChannelPipeline 也实现了ChannelInboundInvoker和*ChannelOutboundInvoker, * * ChannelPipeline 持有ChannelHandlerContext链表, * 对于ChannelInboundInvoker和ChannelOutboundInvoker事件 * ChannelPipeline 只是委派给ChannelHandlerContext链表中每一个 * ChannelHandlerContext处理,ChannelHandlerContext再调用 * 相应的ChannelInboundHandler 或ChannelOutboundHandler方法 * * ChannelPipeline 实现ChannelInboundInvoker和ChannelOutboundInvoker * 目的:只是平滑地将事件委派出去。 **/
/** * Enables a {@link ChannelHandler} to interact with its {@link ChannelPipeline} * and other handlers. Among other things a handler can notify the next {@link ChannelHandler} in the * {@link ChannelPipeline} as well as modify the {@link ChannelPipeline} it belongs to dynamically. * * ChannelHandlerContext 是ChannelPipeline与ChannelHandler之间的粘合剂,负责事件透传至ChannelHandler及调用上或下一个ChannelHandler * DefaultChannelPipeline 持有N个ChannelHandlerContext(链表结构),每一个ChannelHandlerContext对应一个ChannelHandler, * ChannelHandlerContext创建于:channel.pipeline().addLast(ChannelHandler)方法。 * 事件源于ChannelPipeline-》链表Head(或Tail)-》ChannelHandlerContext-》ChannelHandler * 链表下一个(或上一个)->ChannelHandlerContext-》ChannelHandler * 链表下一个(或上一个)->ChannelHandlerContext-》ChannelHandler * 调用过程:ChannelPipeline--》ChannelHandlerContext--》ChannelHandler * <h3>Notify</h3> * 你能够在ChannelHander中调用ChannelHandlerContext的各种方法来触发相邻的ChannelHanndler事件。 * 一般情况下: 你在ChannelHander.channelActive(ChannelHandlerContext ctx) 方法中调用ChannelHandlerContext.fireChannelActive * 会触发下一个 ChannelHander.channelActive,如果没有调用,则下一个(之后的)ChannelHander不会被执行。 * * * <h3>Modifying a pipeline</h3> * 你能够通过ChannelHandlerContext.pipeline()方法获取ChannelPipeline,从而在运行时动态添加修改ChannelHandlers * * * <h3>Retrieving for later use</h3> * 你能够保存ChannelHandlerContext对象,以使之后使用。 * 例如在另外一个线程(非netty内部IO线程)触发事件 * * public class MyHandler extends ChannelDuplexHandler { * * private ChannelHandlerContext ctx; * * public void beforeAdd(ChannelHandlerContext ctx) { * this.ctx = ctx; * } * * public void login(String username, password) { * ctx.write(new LoginMessage(username, password)); * } * ... * } * </pre> * * <h3>Storing stateful information</h3> * 保存状态信息(线程安全的) * 你可以使用 attr(AttributeKey<T> key);方法存储状态信息,以便之后需要时取出。 * 请参考ChannelHandler了解状态信息管理 * * <h3>A handler can have more than one context</h3> * 请注意一个ChannelHandler 实例能够添加到多个ChannelPipeline中或同一个ChannelPipeline添加多次, * 每一次添加,都创建一个新的ChannelHandlerContext与其对应,即同一个ChannelHandler 实例可能对应 * 多个ChannelHandlerContext,在通过ChannelHandlerContext.attr保存或获取变量时,是保存在ChannelHandlerContext * 中,因而虽然只有一个ChannelHandler 实例,但添加的变量不是共享的。 * 该变量的范围:同一个Channel.pipeline().链表中同一个ChannelHandlerContext 范围。 * */ public interface ChannelHandlerContext extends AttributeMap, ChannelInboundInvoker, ChannelOutboundInvoker { /** * 返回绑定到ChannelHandlerContext的Channel */ Channel channel(); /** * 返回io线程对象(EventExecutor),用于执行内部IO任务 */ EventExecutor executor(); /** * * ChannelPipeline.add("name",ChannelHandler)--这个NAME */ String name(); /** * 返回ChannelHandlerContext对应的ChannelHandler(每一个ChannelHandlerContext对应一个ChannelHandler) */ ChannelHandler handler(); /** * 如果对应的ChannelHandler从ChannelPipeline被迁移,则返回true */ boolean isRemoved(); /** * 以下方法调用 ChannelHander相应方法:如fireChannelRegistered,则调用channelRegistered * DefaultChannelHandlerContext 中还实现了下一个或上一个ChannelHandler的事件触发。 **/ ChannelHandlerContext fireChannelRegistered(); ChannelHandlerContext fireChannelUnregistered(); ChannelHandlerContext fireChannelActive(); ChannelHandlerContext fireChannelInactive(); ChannelHandlerContext fireExceptionCaught(Throwable cause); ChannelHandlerContext fireUserEventTriggered(Object evt); ChannelHandlerContext fireChannelRead(Object msg); ChannelHandlerContext fireChannelReadComplete(); ChannelHandlerContext fireChannelWritabilityChanged(); ChannelHandlerContext read(); ChannelHandlerContext flush(); /** * 返回ChannelPipeline */ ChannelPipeline pipeline(); /** * Return the assigned {@link ByteBufAllocator} which will be used to allocate {@link ByteBuf}s. */ ByteBufAllocator alloc(); /** * @deprecated Use {@link Channel#attr(AttributeKey)} */ @Deprecated @Override <T> Attribute<T> attr(AttributeKey<T> key); /** * @deprecated Use {@link Channel#hasAttr(AttributeKey)} */ @Deprecated @Override <T> boolean hasAttr(AttributeKey<T> key); } abstract class AbstractChannelHandlerContext extends DefaultAttributeMap implements ChannelHandlerContext, ResourceLeakHint { //对应的ChannelHandler 是inbound?则处理ChannelInboundHandler 事件 private final boolean inbound //对应的ChannelHandler 是outbound?则处理ChannelOutboundHandler 事件 private final boolean outbound; //持有pipeline,ChannelHandlerContext与pipeline 是多对一关系 private final DefaultChannelPipeline pipeline; //ChannelHander 对应的名字 private final String name; //ChannelHandlerContext链,指向下一个ChannelHandlerContext, //DefaultChannelPipeline.addLast(ChannelHandler)建立的ChannelHandlerContext链 volatile AbstractChannelHandlerContext next; //ChannelHandlerContext链,指向上一个ChannelHandlerContext //DefaultChannelPipeline持有链头指向head //DefaultChannelPipeline.addLast(ChannelHandler)建立的ChannelHandlerContext链 //DefaultChannelPipeline持有链尾指向tail volatile AbstractChannelHandlerContext prev; /** * 构建器 * **/ AbstractChannelHandlerContext(DefaultChannelPipeline pipeline, EventExecutor executor, String name, boolean inbound, boolean outbound) { this.name = ObjectUtil.checkNotNull(name, "name"); this.pipeline = pipeline; this.executor = executor; this.inbound = inbound; this.outbound = outbound; } /* * firexxxx方法: * 以fireChannelActive为例 ,channelActive属于Inbound事件 * 从当前ChannelHandlerContext向下查找每一个inbound==true的ChannelHandlerContext,找到后 * 调用其对应handler.channelActive(ctx),channelActive内部处理完逻辑后,如果需要调用下一个 * ChannelHander.channelActive(ctx),则在channelActive内部写:ctx.fireChannelActive() * 由此继续循环调用下一个ChannelHandler.channelActive * */ @Override public ChannelHandlerContext fireChannelActive() { final AbstractChannelHandlerContext next = findContextInbound(); invokeChannelActive(next); return this; } private AbstractChannelHandlerContext findContextInbound() { AbstractChannelHandlerContext ctx = this; do { ctx = ctx.next; } while (!ctx.inbound); return ctx; } static void invokeChannelActive(final AbstractChannelHandlerContext next) { EventExecutor executor = next.executor(); if (executor.inEventLoop()) { next.invokeChannelActive(); } else { executor.execute(new Runnable() { @Override public void run() { next.invokeChannelActive(); } }); } } private void invokeChannelActive() { if (invokeHandler()) { try { ((ChannelInboundHandler) handler()).channelActive(this); } catch (Throwable t) { notifyHandlerException(t); } } else { fireChannelActive(); } } /** * wirte属于outbound事件,当通过ctx.write()方法被调用时,查找当前ChannelHandlerContext的上一个 * ChannelHandlerContext,调用其write方法,-》nextChannelHander.write -->next ....-->链表头 * DefaultPipeLine.HeadContext 实例.write :最终调用channel.unsafe.write 真正的向网络流中写出 **/ private void write(Object msg, boolean flush, ChannelPromise promise) { AbstractChannelHandlerContext next = findContextOutbound(); final Object m = pipeline.touch(msg, next); EventExecutor executor = next.executor(); if (executor.inEventLoop()) { if (flush) { next.invokeWriteAndFlush(m, promise); } else { next.invokeWrite(m, promise); } } else { //如果不是NioEventLoop内部io线程则创建任务添加到内部io线程执行队列中等待执行 AbstractWriteTask task; if (flush) { task = WriteAndFlushTask.newInstance(next, m, promise); } else { task = WriteTask.newInstance(next, m, promise); } safeExecute(executor, task, promise, m); } } private void invokeWrite(Object msg, ChannelPromise promise) { try { ((ChannelOutboundHandler) handler()).write(this, msg, promise); } catch (Throwable t) { notifyOutboundHandlerException(t, promise); } } private AbstractChannelHandlerContext findContextOutbound() { AbstractChannelHandlerContext ctx = this; do { ctx = ctx.prev; } while (!ctx.outbound); return ctx; } } /** *DefaultChannelHandlerContext 在AbstractChannelHandlerContext基础上,添加了判断是ChannelHandler是 * ChannelInboundHandler 还是ChannelOutboundHandler的方法 * */ final class DefaultChannelHandlerContext extends AbstractChannelHandlerContext { private final ChannelHandler handler; DefaultChannelHandlerContext( DefaultChannelPipeline pipeline, EventExecutor executor, String name, ChannelHandler handler) { super(pipeline, executor, name, isInbound(handler), isOutbound(handler)); if (handler == null) { throw new NullPointerException("handler"); } this.handler = handler; } @Override public ChannelHandler handler() { return handler; } private static boolean isInbound(ChannelHandler handler) { return handler instanceof ChannelInboundHandler; } private static boolean isOutbound(ChannelHandler handler) { return handler instanceof ChannelOutboundHandler; } }