Netty4 4_ChannelHandler在ChannelPipe中的运行顺序

4 篇文章 0 订阅

ChannelPipeline、ChannelHandlerContext和ChannelHandler三者之间关系的模型:


接下来稍微了解一下ChannelHandler的类模型吧


从中可以看见,Channel有inbound和outbound之分


再看一下ChannelInboundHandler、ChannelOutboundHandler的方法:

     

可以看到其实有些ChannelHandler的有些操作属于outbound,有些属于intbound操作,分别被封装在ChannelOutBoundHandler和ChannelInboundHandler中



再看一下ChannelHandlerContext的实现类DefaultChannelHandlerContext的属性




再看一下ChannelPipeline实现类DefaultChannelPipeline




从上面代码可以看出来,其实生成的DefaultChannelPipe中的ChannelHandlerContext双向链表就是一个


而HeadHandler其实就是一个ChannelOutboundHandler类,而TailHandler其实就是一个ChannelInboundHandler类


我们看一下DefaultChannelHandlerContext一些操作方法



从中可以看到属于inboudHandler的方法前面都带有一个fire,再看一下outbound、和inboud两种方法的操作上有什么大的区别呢?



先看一下inbound操作的register(就以register为代表吧)操作

//DefaultChannelPipeline
@Override
    public ChannelPipeline fireChannelRegistered() {
        head.fireChannelRegistered();                   //head是一个HeadHandler对应的DefaultChannelHandlerContext
        return this;
    }


再看DefaultChannelHandlerContext中的实现

//DefaultChannelHandlerContext
@Override
    public ChannelHandlerContext fireChannelRegistered() {
        final DefaultChannelHandlerContext next = findContextInbound();  // 找到下一个ChannelInboudHandler
        EventExecutor executor = next.executor();
        if (executor.inEventLoop()) {
            next.invokeChannelRegistered();
        } else {
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    next.invokeChannelRegistered();
                }
            });
        }
        return this;
    }

    private void invokeChannelRegistered() {
        try {
            ((ChannelInboundHandler) handler).channelRegistered(this);
        } catch (Throwable t) {
            notifyHandlerException(t);
        }
    }



再看一下findContextInbound的实现

//DefaultChannelHandlerContext
 private DefaultChannelHandlerContext findContextInbound() {
        DefaultChannelHandlerContext ctx = this;
        do {
            ctx = ctx.next;
        } while (!ctx.inbound);
        return ctx;                  
    }

可见findContextInboud()方法找到下一个方法起的ChannelInboundHandler对应的ChannelHandlerContext返回


incokeChannelRegistered()中将register交给了ChannelInboundHandler中的channelRegistered()来实现,再看ChannelInboundHandlerAdapter中的实现

//ChannelInboundHandlerAdapter
 @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        ctx.fireChannelRegistered();
    }

可见这就是一个循环反复的执行过程,最后以tail的空实现结束。当然你可以再加入自定义的ChannelInboundHandler,对channelRegistered(this)进行重写


再看outbound的channelhandler,我们以read()方法为代表吧

首先我们看一下DefaultChannelPipe中的read()方法吧

//DefaultChannelPipeline
 @Override
    public ChannelPipeline read() {
        tail.read();                      //tail是TailHandler对应的DefaultChannelHandlerContext
        return this;
    }


我们再来看一些DefaultChannelHandlerContext对read()方法

//DefaultChannelHandlerContext
 @Override
    public ChannelHandlerContext read() {
        final DefaultChannelHandlerContext next = findContextOutbound();   //找到下一个outbound对应的DefaultChannelHandlerContext
        EventExecutor executor = next.executor();
        if (executor.inEventLoop()) {
            next.invokeRead();
        } else {
            Runnable task = next.invokeReadTask;
            if (task == null) {
                next.invokeReadTask = task = new Runnable() {
                    @Override
                    public void run() {
                        next.invokeRead();
                    }
                };
            }
            executor.execute(task);
        }
        return this;
    }

    private void invokeRead() {
        try {
            ((ChannelOutboundHandler) handler).read(this);
        } catch (Throwable t) {
            notifyHandlerException(t);
        }
    }



在看一下findContextOutbound()

//DefaultChannelHandlerContext
private DefaultChannelHandlerContext findContextOutbound() {
        DefaultChannelHandlerContext ctx = this;
        do {
            ctx = ctx.prev;
        } while (!ctx.outbound);
        return ctx;
    }


所以ChannelHandler的read()方法也是自己有自己定义,不然他就可以一直运行到HeadHandler中read()方法


所以ChannelHandler的运行过程就是这样的:


当然其中图里面应该是ChannelContext,在这里用handler代理


好了,至此,整个过程也就结束了,可见其实inbound和outboud在ChannelPipe中的实现方式也是差不多的

到这里,你应该理解了他的整个运行过程了,找个例子亲自调试一下,你会理解更透彻的








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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值