ChannelHandler的添加
一般用户会先添加ChannelInitializer这个Handler,通过这个handler获取channel对应的pipeline,将一系列的channelHandler添加到Pipeline上面。主要是通过调用pipeline的addLast方法进行添加。代码示例如下:
bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel channel) throws Exception { channel.pipeline() .addLast(new LengthFieldBasedFrameDecoder(65536, 0, 4, 0, 0)) .addLast(new RpcDecoder(RpcRequest.class)) .addLast(new RpcEncoder(RpcResponse.class)) .addLast(new RpcHandler(handlerMap)); } }) .option(ChannelOption.SO_BACKLOG, 128) .childOption(ChannelOption.SO_KEEPALIVE, true);
addLast方法流程:
1.判断是否重复添加
2.创建节点并添加到链表中
3.回调添加完成事件
public ChannelPipeline addLast(EventExecutorGroup executor, ChannelHandler... handlers) { if(handlers == null) { throw new NullPointerException("handlers"); } else { ChannelHandler[] arr$ = handlers; int len$ = handlers.length; for(int i$ = 0; i$ < len$; ++i$) { ChannelHandler h = arr$[i$]; if(h == null) { break; } this.addLast(executor, this.generateName(h), h); } return this; } }
public ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler) {
synchronized(this) {
this.checkDuplicateName(name);
DefaultChannelHandlerContext newCtx = new DefaultChannelHandlerContext(this, group, name, handler);
this.addLast0(name, newCtx);
return this;
}
}
这里检查是否重复添加ChannelHandler,是通过checkDuplicateName,而这个方法的内部就是判断一个HashMap的key中是否有这个ChannelHandler的名字。
private void checkDuplicateName(String name) { if(this.name2ctx.containsKey(name)) { throw new IllegalArgumentException("Duplicate handler name: " + name); } }
如果没有重复,使用这个handler创建一个ChannelHandlerContext节点,这里传入group是null。
DefaultChannelHandlerContext(DefaultChannelPipeline pipeline, EventExecutorGroup group, String name, ChannelHandler handler) { super(pipeline, group, name, isInbound(handler), isOutbound(handler)); if(handler == null) { throw new NullPointerException("handler"); } else { this.handler = handler; } }
然后就是就是将channelHandler添加至pipeline中了,逻辑其实就是将一个新的节点添加到双向链表最后一个节点的前面。并且将channelHandlerContext的名字和实例放入到hashMap中。
private void addLast0(String name, AbstractChannelHandlerContext newCtx) { checkMultiplicity(newCtx); AbstractChannelHandlerContext prev = this.tail.prev; newCtx.prev = prev; newCtx.next = this.tail; prev.next = newCtx; this.tail.prev = newCtx; this.name2ctx.put(name, newCtx); this.callHandlerAdded(newCtx); }
最后节点添加完成进行回调callHandlerAdded,最后会调用handlerAdded这个方法,这个方法我们是可以进行重写的,可以在channelHandler添加到pipeline上之后处理一些事情。
private void callHandlerAdded(final ChannelHandlerContext ctx) { if(ctx.channel().isRegistered() && !ctx.executor().inEventLoop()) { ctx.executor().execute(new Runnable() { public void run() { DefaultChannelPipeline.this.callHandlerAdded0(ctx); } }); } else { this.callHandlerAdded0(ctx); } } private void callHandlerAdded0(ChannelHandlerContext ctx) { try { ctx.handler().handlerAdded(ctx); } catch (Throwable var6) { boolean removed = false; try { this.remove((AbstractChannelHandlerContext)((AbstractChannelHandlerContext)ctx)); removed = true; } catch (Throwable var5) { if(logger.isWarnEnabled()) { logger.warn("Failed to remove a handler: " + ctx.name(), var5); } } if(removed) { this.fireExceptionCaught(new ChannelPipelineException(ctx.handler().getClass().getName() + ".handlerAdded() has thrown an exception; removed.", var6)); } else { this.fireExceptionCaught(new ChannelPipelineException(ctx.handler().getClass().getName() + ".handlerAdded() has thrown an exception; also failed to remove.", var6)); } } }
ChannelHandler的删除
使用场景:ChannelInitializer这个Handler最后会将自己删除;.权限校验,第一个数据包会检验权限,如果不满足直接关闭当前的channel,如果满足将权限校验移除。
流程:
1.找到节点
2.链表的删除
3.回调删除Handler事件
private AbstractChannelHandlerContext remove(final AbstractChannelHandlerContext ctx) { assert ctx != this.head && ctx != this.tail; AbstractChannelHandlerContext context; Future future; synchronized(this) { if(!ctx.channel().isRegistered() || ctx.executor().inEventLoop()) { this.remove0(ctx); return ctx; } future = ctx.executor().submit(new Runnable() { public void run() { DefaultChannelPipeline var1 = DefaultChannelPipeline.this; synchronized(DefaultChannelPipeline.this) { DefaultChannelPipeline.this.remove0(ctx); } } }); context = ctx; } waitForFuture(future); return context; }
void remove0(AbstractChannelHandlerContext ctx) {
AbstractChannelHandlerContext prev = ctx.prev;
AbstractChannelHandlerContext next = ctx.next;
prev.next = next;
next.prev = prev;
this.name2ctx.remove(ctx.name());
this.callHandlerRemoved(ctx);
}
最后也会回调handlerRemoved方法,该方法会在handler从pipeline中删除时被调用。这里的handlerAdded和handlerRemoved都是对channelHandler生命周期的一个监听方法。