netty笔记-Pipeline的事件触发

2018-07-12  本文已影响28人  兴浩

1. DefaultChannelPipeline的 fireChannelRead事件

DefaultChannelPipeline中事件的触发是通过fire开头的方法来触发,其内部调用了AbstractChannelHandlerContext的相关的invoke静态方法

    @Override
    public final ChannelPipeline fireUserEventTriggered(Object event) {
        AbstractChannelHandlerContext.invokeUserEventTriggered(head, event);
        return this;
    }

    @Override
    public final ChannelPipeline fireChannelRead(Object msg) {
        AbstractChannelHandlerContext.invokeChannelRead(head, msg);
        return this;
    }

    @Override
    public final ChannelPipeline fireChannelReadComplete() {
        AbstractChannelHandlerContext.invokeChannelReadComplete(head);
        return this;
    }

2. invokeChannelRead静态方法

invokeChannelRead静态方法实际上是调用了AbstractChannelHandlerContext的invokeChannelRead实例方法

    static void invokeChannelRead(final AbstractChannelHandlerContext next, Object msg) {
        final Object m = next.pipeline.touch(ObjectUtil.checkNotNull(msg, "msg"), next);
        EventExecutor executor = next.executor();
        if (executor.inEventLoop()) {
            next.invokeChannelRead(m);
        } else {
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    next.invokeChannelRead(m);
                }
            });
        }
    }

3. invokeChannelRead实例方法

调用了handler()的channelRead方法

    private void invokeChannelRead(Object msg) {
        if (invokeHandler()) {
            try {
                ((ChannelInboundHandler) handler()).channelRead(this, msg);
            } catch (Throwable t) {
                notifyHandlerException(t);
            }
        } else {
            fireChannelRead(msg);
        }
    }

3.1 HeadContext

HeadContext实现了Handler接口,所以handler方法就返回其自己,最终调用的是HeadContext的channelRead方法

 final class HeadContext extends AbstractChannelHandlerContext
            implements ChannelOutboundHandler, ChannelInboundHandler {

        @Override
        public ChannelHandler handler() {
            return this;
        }

        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
            ctx.fireChannelRead(msg);
        }
}

4. AbstractChannelHandlerContext的fireChannelRead事件

    @Override
    public ChannelHandlerContext fireChannelRead(final Object msg) {
        invokeChannelRead(findContextInbound(), msg);
        return this;
    }

这个环节应该看起来跟DefaultChannelPipeline的 fireChannelRead事件是很相似的,不同点在于这里调用的对象是findContextInbound()

4.1 findContextInbound

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

由于AbstractChannelHandlerContext是一个链表结果,其通过next寻找下个对象,所以next找到的对象应该是 1243这个引用对象

5. 触发ChannelInboundHandler事件

public class EchoServerHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        // 将消息记录到控制台
        ByteBuf in = (ByteBuf) msg;
        System.out.println( "Server received: " + in.toString(CharsetUtil.UTF_8));
        // 将接收到的消息写给发送者,而不冲刷出站消息
        ctx.write(in);
    }
}

完整的堆栈流程信息

6.ChannelInvoker的实现

实现ChannelInboundInvoker和ChannelOutboundInvoker的类有2种

  1. ChannelHandlerContext
  2. ChannelPipeline

7.ChannelPipeline和ChannelHandlerContext的关系

7.1DefaultChannelHandlerContext的初始化

    private AbstractChannelHandlerContext newContext(EventExecutorGroup group, 
String name, ChannelHandler handler) {
        return new DefaultChannelHandlerContext(this, childExecutor(group), name, 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;
    }
    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;
        ordered = executor == null || executor instanceof OrderedEventExecutor;
    }

参考:
https://www.jianshu.com/p/4848729baf94

上一篇下一篇

猜你喜欢

热点阅读