您好,登录后才能下订单哦!
这篇文章主要介绍“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当如何存储”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。