指点成金-最美分享吧

登录

Netty源码分析-ChannelInitializer

佚名 举报

篇首语:本文由小编为大家整理,主要介绍了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的主要内容,如果未能解决你的问题,请参考以下文章