ChannelPipeline

概述

  对于一个请求,可能会需要很多的处理逻辑,如果把所有的处理逻辑都放在一个ChannelHandler中,那么代码会十分的臃肿,因此需要把逻辑放在不同的ChannelHandler中实现面向对象的单一职责原则。Netty使用责任链模式把负责不同逻辑的ChannelHandler组合在一起,ChannelPipeline就是ChannelHandler的容器,每一个新建的Channel,Netty都会自动为之分配一个新的ChannelPipeline,这种分配是自动的,且这种绑定在netty整个生命周期中是永久性的。ChannelPipeline会负责Channel所有事件的处理。

  ChannelPipeline会按照相反的顺序调用ChannelHandler处理入栈和出栈事件。

  

  

源码  

addBefor

  把名称为name的handler添加到baseName的前面,调用了一个重载的方法。

    @Override
    public final ChannelPipeline addBefore(String baseName, String name, ChannelHandler handler) {
        return addBefore(null, baseName, name, handler);
    }

  group传入的是null,不需要考虑。

  • 首先注意到整个代码用synchronized包裹起来,说明这是ChannelPipe是一个线程安全的对象,这是因为netty允许在运行时候动态修改ChannelPipe的内容,那么就存在修改线程和正常运行线程同时访问ChannelPipe的情况,需要使用synchronized来避免这种潜在的线程不安全问题。
  • checkMultiplicity判断handler是否可以共享,如果handler已经添加且不可共享,抛出异常。
  • 对handler的名称进行检查(filterName),如果名称重复抛出异常,如果name为Null则生成一个name
  • 调用getContextOrDie从容器中找到baseName的handler,如这个名字暗示,如果没有找到就抛出异常
  • 新建ChannelHandlerContext作为新handler的上下文,并添加到Pipeline里,pipeline说白了就是个双向链表,添加的方法也很简单
    @Override
    public final ChannelPipeline addBefore(
            EventExecutorGroup group, String baseName, String name, ChannelHandler handler) {
        final AbstractChannelHandlerContext newCtx;
        final AbstractChannelHandlerContext ctx;
        synchronized (this) {
            checkMultiplicity(handler);
            name = filterName(name, handler);
            ctx = getContextOrDie(baseName);

            newCtx = newContext(group, name, handler);

            addBefore0(ctx, newCtx);

            // If the registered is false it means that the channel was not registered on an eventloop yet.
            // In this case we add the context to the pipeline and add a task that will call
            // ChannelHandler.handlerAdded(...) once the channel is registered.
            if (!registered) {
                newCtx.setAddPending();
                callHandlerCallbackLater(newCtx, true);
                return this;
            }

            EventExecutor executor = newCtx.executor();
            if (!executor.inEventLoop()) {
                newCtx.setAddPending();
                executor.execute(new Runnable() {
                    @Override
                    public void run() {
                        callHandlerAdded0(newCtx);
                    }
                });
                return this;
            }
        }
        callHandlerAdded0(newCtx);
        return this;
    }

猜你喜欢

转载自www.cnblogs.com/AshOfTime/p/10903044.html