Netty源码分析之ChannelHandler的添加与删除
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生命周期的一个监听方法。

浙公网安备 33010602011771号