在上一篇实例化NioServerSocketChannel中,
protected DefaultChannelPipeline newChannelPipeline() {
return new DefaultChannelPipeline(this);
}
看看DefaultChannelPipeline的继续结构,并不复杂。
protected DefaultChannelPipeline(Channel 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;
}
TailContext和HeadContext都是DefaultChannelPipline的内部类。
HeadContext(DefaultChannelPipeline pipeline) {
//设置属性
super(pipeline, null, HEAD_NAME, false, true);
unsafe = pipeline.channel().unsafe();
setAddComplete();
}
第四个参数表示inbound,第五个表示outbound,这里的HeadContext是outbound的,那么表示处理出站的handler。相反的TailContext是处理入站的handler。
示例代码中都是addLast,我们就先看看addLast方法。
public final ChannelPipeline addLast(ChannelHandler... handlers) {
return addLast(null, handlers);
}
public final ChannelPipeline addLast(EventExecutorGroup executor, ChannelHandler... handlers) {
if (handlers == null) {
throw new NullPointerException("handlers");
}
for (ChannelHandler h: handlers) {
if (h == null) {
break;
}
addLast(executor, null, h);
}
return this;
}
public final ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler) {
final AbstractChannelHandlerContext newCtx;
synchronized (this) {
//检查是否添加过这个handler,通过added属性判断
checkMultiplicity(handler);
//新建DefaultChannelHandlerContext类
newCtx = newContext(group, filterName(name, handler), handler);
//将包装后的DefaultChannelHandlerContext类加入双向链表
//将会被放在headcontext和tailcontext之间
addLast0(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.
//判断channel是否注册过eventloop,如果没有需要添加任务,并在
//channel注册的时候调用ChannelHnadler.handlerAdded()方法
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;
}
上述将添加任务后,会在bind的后续代码中register0方法内执行pipeline.invokeHandlerAddedIfNeeded(),最后一步就会执行对应的ChannelInitializer的initChannel方法。
总结下:
- 在创建channnel的时候,会同时创建pipeline对象进行绑定
- pipeline是一个双端队列,初始化的时候头会新建好head和tail,前者是outbound,后者是inbound。