吃透Netty源码系列八之管道ChannelPipeline

吃透Netty源码系列八之管道ChannelPipeline简介

  • ChannelInboundInvoker接口
  • ChannelOutboundInvoker接口
  • ChannelPipeline接口
  • ChannelHandlerContext接口
    • AbstractChannelHandlerContext抽象类
      • DefaultChannelHandlerContext
  • ChannelHandler接口
    • ChannelInboundHandler接口
    • ChannelOutboundHandler接口
    • ChannelHandlerAdapter抽象类
      • ChannelInboundHandlerAdapter实现类
      • ChannelOutboundHandlerAdapter实现类
  • DefaultChannelPipeline数据的入站出站

ChannelInboundInvoker接口

这个就是入站调用者的接口,也就是说有信息过来了,他可能会触发哪些事件:
吃透Netty源码系列八之管道ChannelPipeline_第1张图片
具体的都是一些接受消息的事件方法,也就是被动的。

ChannelOutboundInvoker接口

有来的数据,当然有写出去的啦:
吃透Netty源码系列八之管道ChannelPipeline_第2张图片
具体都是一些发送消息事件方法,基本都是主动的。

ChannelPipeline接口

而我们的管道也是继承上面的接口的,也就是一个主动的调用者:
吃透Netty源码系列八之管道ChannelPipeline_第3张图片
也就是说所有的进出信息都需要经过管道,所有的处理事件也会经过管道。我们来看看管道自己定义了哪些接口,没截完整,有点长,但是可以看出来基本都是一些增删改查的操作,还有一些出站入站接口的覆盖:
吃透Netty源码系列八之管道ChannelPipeline_第4张图片
吃透Netty源码系列八之管道ChannelPipeline_第5张图片
所以可以看出来,管道就是个容器,管理着里面的处理器。

ChannelHandlerContext接口

通道处理器上下文接口,也是个主动的调用者,这个东西其实就是处理器的包装,处理器只要负责处理数据,至于数据是哪里来,又要往哪里去,处理器之间怎么通信,处理器怎么和管道交互,都由处理器上下文来管理,而且管道中其实存放的是处理器上下文,处理器是被包装在里面的,这个后面我们会看到,先来看看这个接口:

吃透Netty源码系列八之管道ChannelPipeline_第6张图片
他也是实现了上面的出站入站接口,因为要相应管道的操作呀,他还实现了一个AttributeMap接口,这个是给通道设置属性的,后面会讲到。来看看他的接口方法:
吃透Netty源码系列八之管道ChannelPipeline_第7张图片

除了入站的操作外,还保存了通道,事件执行器,处理器,字节缓冲区分配器,管道,可见他就是跟这些交互的桥梁啊。

AbstractChannelHandlerContext抽象类

实现了ChannelHandlerContext接口,和资源泄露提示的接口ResourceLeakHint
吃透Netty源码系列八之管道ChannelPipeline_第8张图片
他基本已经把所有的处理器上下文接口都实现了,除了handler()方法,内部还定义了HeadContextTailContext两个上下文,作为基本处理器,具体后面会讲。他没实现handler()方法,具体交给默认实现类实现。HeadContextTailContext的处理器就是他们本身。

DefaultChannelHandlerContext

AbstractChannelHandlerContext默认实现类,实现了handler()方法,就是创建时候传进来的处理器。

final class DefaultChannelHandlerContext extends AbstractChannelHandlerContext {
     
	//保存处理器
    private final ChannelHandler handler;

    DefaultChannelHandlerContext(
            DefaultChannelPipeline pipeline, EventExecutor executor, String name, ChannelHandler handler) {
     
        super(pipeline, executor, name, handler.getClass());
        this.handler = handler;//设置处理器
    }

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

ChannelHandler接口

这个就是我们的处理器啦,他只是个原始接口,只有处理器的添加和删除事件:
吃透Netty源码系列八之管道ChannelPipeline_第9张图片

ChannelInboundHandler接口

入站处理器接口,这个就是定义入站处理器要做哪些操作,其实和前面的ChannelInboundInvoker是对应的,只是处理器是负责真正的处理,调用者负责触发某些事件:
吃透Netty源码系列八之管道ChannelPipeline_第10张图片

ChannelOutboundHandler接口

出站处理器接口也类似:
吃透Netty源码系列八之管道ChannelPipeline_第11张图片

ChannelHandlerAdapter抽象类

他是处理器实现的一个基本骨架,他实现的添加和删除方法都是空的,需要子类覆盖:
吃透Netty源码系列八之管道ChannelPipeline_第12张图片

ChannelInboundHandlerAdapter实现类

我们常用的是这个,他继承了ChannelHandlerAdapter,还实现了ChannelInboundHandler接口,所以他就可以处理入站事件啦:
吃透Netty源码系列八之管道ChannelPipeline_第13张图片
其实他的所有方法默认都是不触发的,因为有Skip标注,这个我前面有讲过,处理器会匹配相应的处理方法,标注了就不会被匹配到了,也就跳过这个处理器了,也就是默认子类不覆盖方法就是不处理的:
吃透Netty源码系列八之管道ChannelPipeline_第14张图片
我们可以看看ChannelInboundHandlerAdapter源码:

public class ChannelInboundHandlerAdapter extends ChannelHandlerAdapter implements ChannelInboundHandler {
     

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

   
    @Skip
    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
     
        ctx.fireChannelUnregistered();
    }

  
    @Skip
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
     
        ctx.fireChannelActive();
    }

    @Skip
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
     
        ctx.fireChannelInactive();
    }


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


    @Skip
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
     
        ctx.fireChannelReadComplete();
    }


    @Skip
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
     
        ctx.fireUserEventTriggered(evt);
    }


    @Skip
    @Override
    public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
     
        ctx.fireChannelWritabilityChanged();
    }

    @Skip
    @Override
    @SuppressWarnings("deprecation")
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
            throws Exception {
     
        ctx.fireExceptionCaught(cause);
    }
}

默认全是跳过的,其实里面的实现ctx.fireXX也是继续传递给下一个处理器处理。

ChannelOutboundHandlerAdapter实现类

当然出站的也类似:
吃透Netty源码系列八之管道ChannelPipeline_第15张图片

DefaultChannelPipeline数据的入站出站

首先他是ChannelPipeline接口的实现类,拥有管理通道上下文的能力,同时又实现了出站入站调用者,也就是有能力可以触发那些事件:
吃透Netty源码系列八之管道ChannelPipeline_第16张图片
我们先画个大致的图,看看他是怎么管理的:
吃透Netty源码系列八之管道ChannelPipeline_第17张图片
如果有出入站事件来了,传播的路径可能是这样的,所有事件都传递下去了:
吃透Netty源码系列八之管道ChannelPipeline_第18张图片
当然也可能某个处理器处理完了不传递数据了,比如入站事件入站处理器1处理了,然后就完了,因为他没调用ctx.fireChannelRead(msg);
吃透Netty源码系列八之管道ChannelPipeline_第19张图片
当然出如站处理器也可以这样,入站数据传递到入站处理器3,然后直接在入站处理器3这里进行写,然后出站数据传递到出站处理器2里不再传递了,其实一般的写只是写在出站缓冲区中,还并没有写进通道里,这个具体后面会详细讲:
吃透Netty源码系列八之管道ChannelPipeline_第20张图片
所以这个入站出站的顺序和操作非常灵活,只要搞明白原理,就觉得这个真的非常强大。今天只是先做个铺垫,没讲什么源码,下一篇就着重讲这个入站出站的过程和原理,还有里面的一些细节,这个也是很重要的,这样你才能设计出强大的处理器链条,才能用更少的处理器组合出强大的功能,才能再出问题的时候知道要怎么解决问题。

好了,今天就到这里了,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵。

你可能感兴趣的:(吃透Netty源码系列,吃透Netty源码系列,Netty,Netty源码解析,多路复用,nio)