文章

Netty源码篇 ChannelInitializer

前言

ChannelInitializernetty 提供的用来向 channel 的 pipeline 添加 hander 的入口
ChannelInitializer 的初始化过程只能执行一次, 一旦被执行就会将该 ChannelInitializer 移除 pipeline

示例代码

// 启动 netty 服务器
ServerBootstrap bootstrap = new ServerBootstrap();

bootstrap.group(boosGroup, workGroup)
         .channel(NioServerSocketChannel.class)
         //NettyClientInitializer 这里 配置 netty 对消息的处理器
         .childHandler(new NettyServerInitializer(serviceProvider));
// 同步阻塞
ChannelFuture channelFuture = bootstrap.bind(port).sync();

源码解析

// 抽象方法, 需要子类实现
protected abstract void initChannel(C ch) throws Exception;

// 初始化 channel 方法
private boolean initChannel(ChannelHandlerContext ctx) throws Exception {
    // initMap 是一个 set, 因此, 这个 if 里面的只会进一次, 意思是说, 每个 ctx 只能初始化一次
    if (initMap.add(ctx)) {
        try {initChannel((C) ctx.channel());} catch (Throwable cause) {exceptionCaught(ctx, cause);
        } finally {
            // 注意这里: 这里说明一旦初始化完成这个 ChannelInitializer 就将从 pipeline 中移除
            if (!ctx.isRemoved()) {ctx.pipeline().remove(this);}
        }
        return true;
    }
    return false;
}

@Override
@SuppressWarnings("unchecked")
public final void channelRegistered(ChannelHandlerContext ctx) throws Exception {
    // 初始化 channel, 为 true 表示这个 ctx 是第一次初始化, 可能会向 pipeline 中加入了 handler
    // 所以需要从 pipeline 的头部开始重新执行 channelRegistered()
    if (initChannel(ctx)) {ctx.pipeline().fireChannelRegistered();
        removeState(ctx);
    } else {
    	// 否则说明这个 ctx 已经初始化过了, 不会再像 pipline 中加入 handler 了
        ctx.fireChannelRegistered();}
}

   @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        if (ctx.channel().isRegistered()) {
            if (initChannel(ctx)) {removeState(ctx);
            }
        }
    }

License:  CC BY 4.0