快上网专注成都网站设计 成都网站制作 成都网站建设
成都网站建设公司服务热线:028-86922220

网站建设知识

十年网站开发经验 + 多家企业客户 + 靠谱的建站团队

量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决

handler在pipeline当如何存储

这篇文章主要介绍“handler在pipeline当如何存储”,在日常操作中,相信很多人在handler在pipeline当如何存储问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”handler在pipeline当如何存储”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

为乌什等地区用户提供了全套网页设计制作服务,及乌什网站建设行业解决方案。主营业务为网站制作、成都做网站、乌什网站设计,以传统方式定制建设网站,并提供域名空间备案等一条龙服务,秉承以专业、用心的态度为用户提供真诚的服务。我们深信只要达到每一位用户的要求,就会得到认可,从而选择与我们长期合作。这样,我们也可以走得更远!

今天解决2个问题,

1、handler在pipeline当中究竟是如何存储的;

2、在遍历handler的过程中,会根据event的不同,调用不同的handler,这一点是如何实现的。

先研究第一个问题:

TailHandler tailHandler = new TailHandler();
tail = new DefaultChannelHandlerContext(this, null, generateName(tailHandler), tailHandler);

HeadHandler headHandler = new HeadHandler(channel.unsafe());
head = new DefaultChannelHandlerContext(this, null, generateName(headHandler), headHandler);

head.next = tail;
tail.prev = head;

这是DefaultChannelPipeline构造函数当中的一段代码,我们之前提到过,在pipeline当中存在一个双向链表,这里就是把双向链表的头和尾进行了初始化。

之后我们通过addlast方法向pipeline当中添加handler,

DefaultChannelHandlerContext prev = tail.prev;
newCtx.prev = prev;
newCtx.next = tail;
prev.next = newCtx;
tail.prev = newCtx;

这里就是把一个新的handler加入到双向链表当中去。

另一个问题,双向链表当中的元素究竟是什么,

DefaultChannelHandlerContext newCtx =
                    new DefaultChannelHandlerContext(this, invoker, name, handler);

需要看这个,简单理解,把handler放到了一个新的 DefaultChannelHandlerContext 当中。那么它的作用究竟是什么呢?

通过对代码的研究, DefaultChannelHandlerContext其实是一个动态代理类,而我们的各个handler,就是被代理的类。这里有两点需要解释一下。先看下面这段代码

    @Override
    public ChannelFuture write(Object msg, ChannelPromise promise) {
        DefaultChannelHandlerContext next = findContextOutbound(MASK_WRITE);
        next.invoker.invokeWrite(next, msg, promise);
        return promise;
    }

首先,不要被write方法所迷惑,这个方法里面确实执行的write的动作,以及write当中所包含的encode的动作。但是请注意,这个write动作,并不是当前元素的write,而是链表当中下一个元素当中的handler的write,在handler的write方法的末尾,会执行next.write,这里又会执行再下一个元素当中的handler的write。依次类推,实现了链表的遍历。

其次:不要被invoke所迷惑,这里并没有用到java的反射机制,因为 不论你传入什么样的handler,都来自ChannelHandler这个统一的老祖宗。按需要调用不同的方法即可。跟反射一毛钱关系都没有。

然后是第二个问题:

首先明确一个概念:所有的handler来自同一个祖宗ChannelHandler ,而 ChannelHandler 当中的不同方法,对应了netty当中各个不同的事件。

我们在初始化bootstrap的时候,加入了很多个handler,有些负责下行的decode,有些负责上行的encode,我们当然希望,下行的时候,只进入下行相关的handler,上行的时候,只进入上行相关的handler。那么具体是怎么做到的呢?看下面这段代码,鉴于篇幅问题,只摘录了其中一段:

if (handlerType.getMethod(
    "handlerAdded", ChannelHandlerContext.class).isAnnotationPresent(Skip.class)) {
    flags |= MASK_HANDLER_ADDED;
}

在构造一个 DefaultChannelHandlerContext,会有这样的一段代码,我们可以这样理解这段语句:根据handler当中不通方法的注解,来判定当发生某个event的时候,该方法是否执行。

ChannelHandlerAdapter 是 ChannelHandler 一个最基础的实现,我们看一下 ChannelHandlerAdapter 的代码,会发现,每一个方法头部,都会有一个@Skip的注解。也就是说,默认情况下,每一个方法都不会被执行。而在 ChannelHandlerAdapter 的子孙当中,Override了某一个方法, @Skip 就没有了。那么这个handler的这个方法,就会被执行。

至于具体的判定过程,可以参照另一个篇文章android edittext.setInputType,当中按位进行设置的思想。

到此,关于“handler在pipeline当如何存储”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注创新互联网站,小编会继续努力为大家带来更多实用的文章!


分享文章:handler在pipeline当如何存储
网页URL:http://6mz.cn/article/gpcedo.html

其他资讯