Netty4.1源码 :DefaultChannelHandlerContext



 

/**
*   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;
    }
}

猜你喜欢

转载自java12345678.iteye.com/blog/2355374