篇首语:本文由小编为大家整理,主要介绍了Netty源码分析-ChannelInitializer相关的知识,希望对你有一定的参考价值。
ChannelInitializer是一个PPLine的初始化工具,可以往PPLine里面设置Handler。
protected abstract void initChannel(C ch) throws Exception;
我们可以重写此方法来完成初始化动作,往PPLine当中加入Handler。
.childHandler(new ChannelInitializer() @Override public void initChannel(SocketChannel ch) throws Exception System.out.println("initChannel:" + ch.localAddress()); ch.pipeline().addLast("log", new LoggingHandler(LogLevel.INFO)); ch.pipeline().addLast("DiscardHandler", new DiscardHandler()); ch.pipeline().addLast("hexEncoder2", new HexEncoder2()); ch.pipeline().addLast("hexEncoder1", new HexEncoder1()); );
在channel被注册到EventLoop当中时,当前PPLine当中只有一个Handler,就是ChannelInitializer,它的channelRegistered会被调用。在它的initChannel子类回调中往PPLine中加入用户自定义的Handler。
@Override @SuppressWarnings("unchecked") public final void channelRegistered(ChannelHandlerContext ctx) throws Exception //调用子类初始化方法,往PPline里加入Handler,该方法只会调用一次。 //在调用之前PPLine当中只有一个handler。 PPline[---this----] //在调用之后PPLine当中加入了用户自定义的Handler(ABCD) PPline[---this---A---B---C---D---] if (initChannel(ctx)) //重新调用channelRegistered防止事件丢失。 ctx.pipeline().fireChannelRegistered(); //移除当前Handler 移除后变为PPline[---A---B---C---D---] removeState(ctx); else //向下传递事件 ctx.fireChannelRegistered();
子类回到函数,初始化PPLine,成功返回true,同时移除自己。
//子类回调成功返回true,否则返回false private boolean initChannel(ChannelHandlerContext ctx) throws Exception //加入标记,保证方法只执行一次 if (initMap.add(ctx)) // Guard against re-entrance. try //子类回调函数 initChannel((C) ctx.channel()); catch (Throwable cause) // Explicitly call exceptionCaught(...) as we removed the handler before calling initChannel(...). // We do so to prevent multiple calls to initChannel(...). exceptionCaught(ctx, cause); finally //移除当前Handler ChannelPipeline pipeline = ctx.pipeline(); if (pipeline.context(this) != null) pipeline.remove(this); return true; return false;
移除标记位。
private void removeState(final ChannelHandlerContext ctx) //判断当前ctx是否从PPLine当中移除 if (ctx.isRemoved()) //移除执行清空标记位 initMap.remove(ctx); else // The context is not removed yet which is most likely the case because a custom EventExecutor is used. // Let"s schedule it on the EventExecutor to give it some more time to be completed in case it is offloaded. //否则加入EventLoop事件队列,下一轮移除。 ctx.executor().execute(new Runnable() @Override public void run() initMap.remove(ctx); );
/** * @inheritDoc If override this method ensure you call super! */ @Override public void handlerAdded(ChannelHandlerContext ctx) throws Exception //判断channel是否已经注册 if (ctx.channel().isRegistered()) // This should always be true with our current DefaultChannelPipeline implementation. // The good thing about calling initChannel(...) in handlerAdded(...) is that there will be no ordering // surprises if a ChannelInitializer will add another ChannelInitializer. This is as all handlers // will be added in the expected order. //调用子类 if (initChannel(ctx)) // We are done with init the Channel, removing the initializer now. removeState(ctx);
以上是关于Netty源码分析-ChannelInitializer的主要内容,如果未能解决你的问题,请参考以下文章