`

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

 

 

 

  • 大小: 14.9 KB
分享到:
评论

相关推荐

    Netty 4.1源码包

    Netty4.1的源码,欢迎大家下载。.............................................................................................................................................................................

    netty4.1源码

    这个“netty4.1源码”压缩包包含的是Netty框架4.1版本的源代码,对于深入理解Netty的工作原理、性能优化以及自定义功能扩展非常有帮助。 Netty的核心特性包括: 1. **异步非阻塞I/O**:Netty基于Java NIO(非阻塞I...

    netty-4.1 源码包

    这个"Netty-4.1 源码包"包含了Netty框架的源代码,允许开发者深入理解其内部工作原理,优化自定义实现,或者排查问题。 在Netty 4.1 版本中,主要包含以下关键知识点: 1. **NIO (Non-blocking I/O)**: Netty 使用...

    netty 4.1 中文api 帮助文档 + 用户指南

    在本文中,我们将深入探讨 Netty 4.1 的中文API帮助文档和用户指南,以及如何利用这些资源来提升你的网络编程技能。 首先,Netty 4.1 中文API帮助文档是理解 Netty 内部机制的关键工具。它包含了详细的类、接口、...

    netty 4.1中文.CHM

    这个“netty 4.1 中文.CHM”文件是一个压缩包,包含的是Netty 4.1版本的中文版帮助文档,对于开发者来说是一个非常宝贵的资源,特别是对于那些中文为母语的开发者,它提供了方便的理解和学习Netty的途径。...

    Netty-4.1.97.Final源码

    Netty-4.1.97.Final源码提供了对Netty内部机制的深度洞察,对于Java程序员尤其是希望提升网络编程能力或进行定制化开发的人来说,是一份极其宝贵的资料。 首先,让我们从整体上了解Netty的架构设计。Netty采用了...

    netty-common-4.1.65.Final-API文档-中英对照版.zip

    赠送jar包:netty-common-4.1.65.Final.jar; 赠送原API文档:netty-common-4.1.65.Final-javadoc.jar; 赠送源代码:netty-common-4.1.65.Final-sources.jar; 赠送Maven依赖信息文件:netty-common-4.1.65.Final....

    netty案例,netty4.1中级拓展篇八《Netty心跳服务与断线重连》源码

    netty案例,netty4.1中级拓展篇八《Netty心跳服务与断线重连》源码 https://mp.weixin.qq.com/s?__biz=MzIxMDAwMDAxMw==&mid=2650724845&idx=1&sn=8631c590ff4876ba0b7af64df16fc54b&scene=19#wechat_redirect

    netty 4.1 英文api 帮助文档 + 用户指南 chm

    这个压缩包包含的是Netty 4.1的英文API帮助文档和用户指南,对于理解和使用Netty框架非常有帮助。 首先,我们来看`netty 4.1.CHM`文件,这是一个CHM(Compiled Help Manual)格式的帮助文档,通常包含了详细的API...

    netty-all-4.1.68.Final-API文档-中文版.zip

    赠送jar包:netty-all-4.1.68.Final.jar; 赠送原API文档:netty-all-4.1.68.Final-javadoc.jar; 赠送源代码:netty-all-4.1.68.Final-sources.jar; 赠送Maven依赖信息文件:netty-all-4.1.68.Final.pom; 包含...

    netty-all-4.1.68.Final-API文档-中英对照版.zip

    赠送jar包:netty-all-4.1.68.Final.jar; 赠送原API文档:netty-all-4.1.68.Final-javadoc.jar; 赠送源代码:netty-all-4.1.68.Final-sources.jar; 赠送Maven依赖信息文件:netty-all-4.1.68.Final.pom; 包含...

    以netty4.1源码中的EchoServer为例对netty的源码进行分析.docx

    在本文中,我们将深入分析 Netty 4.1 源码中的 EchoServer 示例,以理解其核心组件和工作原理。 首先,我们关注 EchoServer 服务端的初始化,这涉及到两个关键组件:`bossGroup` 和 `workerGroup`。它们都是 `...

    netty-netty-4.1.32.final-remark.zip

    标题 "netty-netty-4.1.32.final-remark.zip" 提到了 Netty 的版本号 4.1.32.Final,这表明这是一个关于 Netty 4.1.32.Final 版本的资料包。"final" 表示这是该版本的最终发布,通常意味着经过了充分测试和稳定。...

    netty-netty-4.1.79.Final.tar.gz

    这个“netty-netty-4.1.79.Final.tar.gz”文件是一个包含Netty 4.1.79.Final版本的压缩包,通常用于Java开发环境。解压后,我们可以得到Netty的源代码、库文件和其他相关资源。 Netty的核心特性包括: 1. **异步...

    netty案例,netty4.1中级拓展篇十三《Netty基于SSL实现信息传输过程中双向加密验证》源码

    netty案例,netty4.1中级拓展篇十三《Netty基于SSL实现信息传输过程中双向加密验证》源码 ...

    netty案例,netty4.1中级拓展篇一《Netty与SpringBoot整合》源码

    netty案例,netty4.1中级拓展篇一《Netty与SpringBoot整合》源码 https://mp.weixin.qq.com/s?__biz=MzIxMDAwMDAxMw==&mid=2650724796&idx=1&sn=ce5dc3c913d464b0e2e4e429a17bb01e&scene=19#wechat_redirect

    netty-all-4.1.32.Final-sources.jar 最新版netty源码全部包

    netty-buffer-4.1.32.Final-sources.jar netty-buffer-4.1.32.Final.jar netty-build-22-sources.jar netty-build-22.jar netty-codec-4.1.32.Final-sources.jar netty-codec-4.1.32.Final.jar netty-codec-...

    netty-netty-4.1.69.Final.tar.gz

    这个“netty-netty-4.1.69.Final.tar.gz”文件是Netty的最新稳定版本,版本号为4.1.69.Final,它是一个压缩包文件,通常包含源码、编译后的类库、文档和其他相关资源。 Netty的核心特点包括: 1. **异步事件驱动**...

    netty案例,netty4.1基础入门篇十一《netty udp通信方式案例Demo》源码

    netty案例,netty4.1基础入门篇十一《netty udp通信方式案例Demo》源码 https://mp.weixin.qq.com/s?__biz=MzIxMDAwMDAxMw==&mid=2650724927&idx=1&sn=a16bc8e98d6a27816da0896adcc83778&scene=19#wechat_redirect

Global site tag (gtag.js) - Google Analytics