在网络编程 - Netty(Channel)中,Channel的初始化,也提到了会一并初始化ChannelPipeline,一个Channel对应着一个ChannelPipeline。
代码在AbstractChannel类中的构造方法:编程
protected AbstractChannel(Channel parent) { this.parent = parent; id = newId(); // 建立一个NioSocketChannel.NioSocketChannelUnsafe的内部类对象 unsafe = newUnsafe(); // 建立一个Pipeline,并把当前的Channel赋值给Pipeline pipeline = newChannelPipeline(); } protected DefaultChannelPipeline newChannelPipeline() { return new DefaultChannelPipeline(this); }
ChannelPipeline的类结构图以下,能够看出ChannelPipeline接口继承了ChannelInboundInvoker和ChannelOutboundInvoker接口。
ChannelInboundInvoker用于入站操做,会调用ChannelPipeline中下一个ChannelInboundHandler的方法,ChannelOutboundInvoker用于出站操做,会调用ChannelPipeline中下一个ChannelOutboundHandler的方法。
DefaultChannelPipeline的构造函数,除了ChannelFuture、Channel、Promise外,还构造了TailContext和HeadContext,再经过next和prev把两个连接起来。segmentfault
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; }
TailContext的类结构图:
HeadContext的类结构图:
能够看出,HeadContext比TailContext多继承了ChannelOutboundHandler接口。
TailContext构造方法,设置pipline,并标志inbound为true。经过类结构图,看出这两个便是ChannelHandler也是ChannelHandlerContext。安全
TailContext(DefaultChannelPipeline pipeline) { super(pipeline, null, TAIL_NAME, true, false); setAddComplete(); }
HeadContext构造方法,设置pipline,并标志outbound为true,另外还设置了unsafe,由于出站涉及到于socket交互。网络
HeadContext(DefaultChannelPipeline pipeline) { super(pipeline, null, HEAD_NAME, false, true); unsafe = pipeline.channel().unsafe(); setAddComplete(); }
在网络编程 - Netty(Channel)中,提到了Channel的初始化,即channel = channelFactory.newChannel()
,这句执行完后,就执行init(channel)
方法。socket
void init(Channel channel) throws Exception { ChannelPipeline p = channel.pipeline(); p.addLast(config.handler()); // 部分代码略 }
addLast方法:ide
public final ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler) { final AbstractChannelHandlerContext newCtx; synchronized (this) { // 检查是否安全 checkMultiplicity(handler); // 根据handler建立一个AbstractChannelHandlerContext newCtx = newContext(group, filterName(name, handler), handler); // 把新的AbstractChannelHandlerContext加入到链表倒二 addLast0(newCtx); if (!registered) { newCtx.setAddPending(); // 给pendingHandlerCallbackHead赋值,并传递newCtx 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; }
checkMultiplicity,在网络编程 - 初识Netty的服务端的例子,EchoServerHandler 是有@ChannelHandler.Sharable注解的,用来标识能被多个channel安全的共享,是线程安全的。若是一个没有表示线程安全的,又被重复使用,就须要抛异常。函数
private static void checkMultiplicity(ChannelHandler handler) { if (handler instanceof ChannelHandlerAdapter) { // 若是没有@Sharable注解,且已经加入过了,则抛异常 ChannelHandlerAdapter h = (ChannelHandlerAdapter) handler; if (!h.isSharable() && h.added) { throw new ChannelPipelineException( h.getClass().getName() + " is not a @Sharable handler, so can't be added or removed multiple times."); } // 设置已加入 h.added = true; } }
根据handler建立一个AbstractChannelHandlerContext。oop
private AbstractChannelHandlerContext newContext(EventExecutorGroup group, String name, ChannelHandler handler) { return new DefaultChannelHandlerContext(this, childExecutor(group), name, handler); } DefaultChannelHandlerContext( DefaultChannelPipeline pipeline, EventExecutor executor, String name, ChannelHandler handler) { // isInbound判断是不是ChannelInboundHandler类型 // isOutbound判断是不是ChannelOutboundHandler类型 super(pipeline, executor, name, isInbound(handler), isOutbound(handler)); if (handler == null) { throw new NullPointerException("handler"); } this.handler = handler; }
addLast0,把新的AbstractChannelHandlerContext加入到链表倒二,headContext <-> nextContext变成headContext <-> newCtx <-> nextContext。this
private void addLast0(AbstractChannelHandlerContext newCtx) { AbstractChannelHandlerContext prev = tail.prev; newCtx.prev = prev; newCtx.next = tail; prev.next = newCtx; tail.prev = newCtx; }
在Channel成功调用doRegister方法注册后,会调用DefaultChannelPipeline类中的invokeHandlerAddedIfNeeded()
方法。
方法调用链是DefaultChannelPipeline#invokeHandlerAddedIfNeeded() -> DefaultChannelPipeline#callHandlerAddedForAllHandlers() -> PendingHandlerCallback#execute() -> PendingHandlerCallback#callHandlerAdded0() -> ChannelInitializer#handlerAdded() -> ChannelInitializer#initChannel()。spa
private boolean initChannel(ChannelHandlerContext ctx) throws Exception { if (initMap.putIfAbsent(ctx, Boolean.TRUE) == null) { // Guard against re-entrance. try { // 这个方法,会执行咱们在.handler(new ChannelInitializer<SocketChannel>()里面的内容 initChannel((C) ctx.channel()); } catch (Throwable cause) { exceptionCaught(ctx, cause); } finally { // 移除ChannelInitializer remove(ctx); } return true; } return false; } private void remove(ChannelHandlerContext ctx) { try { ChannelPipeline pipeline = ctx.pipeline(); if (pipeline.context(this) != null) { pipeline.remove(this); } } finally { initMap.remove(ctx); } }
综上,咱们的双向链表由headContext <-> nextContext变成headContext <-> ChannelInitializer <-> nextContext变成headContext <-> ChannelInitializer <-> newCtx2 <-> newCtx1 <-> nextContext变成headContext <-> newCtx2 <-> newCtx1 <-> nextContext。由于这个时候,ChannelInitializer完成了本身的使命,即执行他的initChannel方法。
Channel、ChannelPipeline、ChannelHandler 以及ChannelHandlerContext 之间的关系。综合这篇和Channel那篇,能够总结出,Channel初始化时,会建立一个ChannelPipeline,ChannelPipeline内部维护这HeadContext和TailContext,ChannelPipeline会add多个ChannelHandler时,会把ChannelHandler保证成HandlerContext,再与已有的双向链表链接起来。