概述
pipeline
, 顾名思义, 就是管道的意思, 事件在pipeline
中传输, 用户可以中断事件, 添加自己的事件处理逻辑, 可以直接将事件中断不再往下传输, 同样可以改变管道的流向, 传递其他事件。- 事件通常分为两种, 一是
inBound
入站事件, 另一种是outBound
出站事件。inBound
事件, 顾名思义, 就是从另一端流向自己的事件, 比如读事件, 连接完成事件等等。outBound
, 是从自己流向另一端的事件, 比如连接事件, 写事件, 刷新缓冲区事件等等。
- 事件是通过
handler
对象进行处理的, 里面封装着事件的处理逻辑.而每个handler
, 是由HandlerContext
进行包装的, 里面封装了对事件传输的操作。 - 每一个
channel
绑定一个pipeline
, 那么pipeline
和handler
又是什么关系?pipeline
可以理解成是一个双向链表, 只是存放的并不是数据而是HandlerContext
, 而HandlerContext
又包装了handler
, 事件传输时, 从头结点(或者尾节点)开始, 找到下一个HandlerContext
, 执行Handler
的业务逻辑, 然后再继续往下走, 直到执行到尾节点(或者头结点, 反向)为止。
继承关系
- 如果属于
ChannelInboundHandler
的子类, 则属于Inbound
类型的handler
。 - 如果属于
ChannelOutboundHandler
的子类, 则属于Outbound
类型的handler
。
pipeline的创建
回到AbstractChannel的构造方法
protected AbstractChannel(Channel parent) {
this.parent = parent;
id = newId();
unsafe = newUnsafe();
pipeline = newChannelPipeline();
}
newChannelPipeline()
protected DefaultChannelPipeline newChannelPipeline() {
//传入当前channel
return new DefaultChannelPipeline(this);
}
DefaultChannelPipeline的构造方法
protected DefaultChannelPipeline(Channel channel) {
this.channel = ObjectUtil.checkNotNull(channel, "channel");
succeededFuture = new SucceededChannelFuture(channel, null);
voidPromise = new VoidChannelPromise(channel, true);
tail = new TailContext(this);
head = new HeadContext(this);
head.next = tail;
tail.prev = head;
}
- 保存了当前
channel
。 - 保存了两个属性
succeededFuture
,voidPromise
, 这两个属性是Future相关的内容, 之后会讲到。 - 初始化了两个节点,
head
节点和tail
节点, 在pipeline
中代表头结点和尾节点
new TailContext(this)
尾结点的构建
final class TailContext extends AbstractChannelHandlerContext implements ChannelInboundHandler {
TailContext(DefaultChannelPipeline pipeline) {
//inbound处理器
super(pipeline, null, TAIL_NAME, true, false);
//将当前节点设置为已添加, head和tail.....
setAddComplete();
}
//自身也是handler
@Override
public ChannelHandler handler() {
return this;
}
//方法省略
}
- 这个是
DefualtPipline
的内部类, 首先看其继承了AbstractChannelHandlerContext
类, 说明自身是个HandlerContext
, 同时也实现ChannelInboundHander
接口, 并且其中的handler()
方法返回了自身, 说明自身也是handler
, 而实现ChannelInboundHander
, 说明自身只处理Inbound
事件。 - 构造方法中, 调用了父类的构造器, 看其中参数
pipeline
是自身所属的pipeline
executor
为nullTAIL_NAME
是当前handler
, 也就是自身的命名true
代表自身是inboundHandler
fasle
代表自身不是outboundHandler
AbstractChannelHandlerContext的构造方法
AbstractChannelHandlerContext(DefaultChannelPipeline pipeline, EventExecutor executor, String name,
boolean inbound, boolean outbound) {
//名字
this.name = ObjectUtil.checkNotNull(name, "name");
//pipeline
this.pipeline = pipeline;
//线程处理器
this.executor = executor;
//事件标识
this.inbound = inbound;
this.outbound = outbound;
ordered = executor == null || executor instanceof OrderedEventExecutor;
}
pipeline
为自身绑定的pipeline
exeutor
是线程执行器, 这里为空inbound
和outbound
是事件标志, 这里分别是true
和false
, 也就是自身属于inboundHnadler
而不属于outboundHandler
new HeadContext(this)
头结点的构建
final class HeadContext extends AbstractChannelHandlerContext
implements ChannelOutboundHandler, ChannelInboundHandler {
private final Unsafe unsafe;
HeadContext(DefaultChannelPipeline pipeline) {
super(pipeline, null, HEAD_NAME, false, true);
unsafe = pipeline.channel().unsafe();
setAddComplete();
}
@Override
public ChannelHandler handler() {
return this;
}
}
- 看过了
tail
节点,head
节点就不难理解, 同样继承了AbstractChannelHandlerContext
, 说明自身是一个HandlerContext
, 与tail
不同的是, 这里实现了ChannelOutboundHandler
接口和ChannelOutboundHandler
接口, 说明其既能处理inbound
事件也能处理outbound
的事件,handler
方法返归自身, 说明自身是一个handler
。 - 在构造方法中初始化了一个
Unsafe
类型的成员变量, 是通过自身绑定的channel
拿到的, 说明这个类中可以进行对channel
的读写操作。这里同样调用了父类的构造方法, 不同的是, 这里inbound
参数传入了false
, 而outbound
参数传入了true
, 这里说明这里标志的事件是outbound
事件。同学们可能疑惑, 为什么同时执行ChannelOutboundHandler
接口和ChannelOutboundHandler
接口,但是标志的事件不同? - 其实这两个地方应用的场景是不同的, 继承
ChannelOutboundHandler
和ChannelOutboundHandler
, 说明其既能处理inbound
事件也能处理outBound
的事件, 但是只有outbound
属性为true
说明自身是一个outboundhandler
, 是一个可以处理inbound
事件的outboundhandler
(估计被绕晕了), 这两种handler
主要是保证在事件传输中保证事件的单方向流动, 在后面事件传输我们能领会到。
AbstractChannelHandlerContext的构造方法
AbstractChannelHandlerContext(DefaultChannelPipeline pipeline, EventExecutor executor, String name,
boolean inbound, boolean outbound) {
//名字
this.name = ObjectUtil.checkNotNull(name, "name");
//pipeline
this.pipeline = pipeline;
//线程处理器
this.executor = executor;
//事件标识
this.inbound = inbound;
this.outbound = outbound;
ordered = executor == null || executor instanceof OrderedEventExecutor;
}
AbstractChannelHandlerContext
的构建和尾结点构建时相同
回到DefaultChannelPipeline的构造方法
protected DefaultChannelPipeline(Channel channel) {
this.channel = ObjectUtil.checkNotNull(channel, "channel");
succeededFuture = new SucceededChannelFuture(channel, null);
voidPromise = new VoidChannelPromise(channel, true);
tail = new TailContext(this);
head = new HeadContext(this);
head.next = tail;
tail.prev = head;
}
介绍完了new TailContext(this)
和new HeadContext(this)
,继续分析
head.next = tail;
tail.prev = head;
tail
节点和head
节点中的next
和prev
属性, 其实是其父类AbstractChannelHandlerContext
, 每一个handlerContext
都拥有这两个属性, 代表自身的下一个节点和上一个节点, 因为我们概述中介绍过pipeline
其实是一个双向链表, 所以其中每一个节点必须有指向其他节点的指针。