Netty4 4_ChannelHandler在ChannelPipe中的运行顺序

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

Netty4 4_ChannelHandler在ChannelPipe中的运行顺序_第1张图片

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

Netty4 4_ChannelHandler在ChannelPipe中的运行顺序_第2张图片

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


再看一下ChannelInboundHandler、ChannelOutboundHandler的方法:

Netty4 4_ChannelHandler在ChannelPipe中的运行顺序_第3张图片     Netty4 4_ChannelHandler在ChannelPipe中的运行顺序_第4张图片

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



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

Netty4 4_ChannelHandler在ChannelPipe中的运行顺序_第5张图片



再看一下ChannelPipeline实现类DefaultChannelPipeline


Netty4 4_ChannelHandler在ChannelPipe中的运行顺序_第6张图片


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

Netty4 4_ChannelHandler在ChannelPipe中的运行顺序_第7张图片

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


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

Netty4 4_ChannelHandler在ChannelPipe中的运行顺序_第8张图片


从中可以看到属于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的运行过程就是这样的:

Netty4 4_ChannelHandler在ChannelPipe中的运行顺序_第9张图片

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


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

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








你可能感兴趣的:(Java,Netty)