在上一篇部落格中,我們看到例子中有一段代碼
try
{
// 一個伺服器助手類
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
//用它來建立新accept的連接配接,用于構造serversocketchannel的工廠類
.channel(NioServerSocketChannel.class)
//在serverBootstrap内部用該handler去處理執行個體化的channel
.childHandler(new ChannelInitializer<SocketChannel>()
{
//當有新accept的時候,這個方法會調用
@Override
public void initChannel(SocketChannel ch)
throws Exception
{
ch.pipeline().addLast(new DiscardServerHandler());
}
});
// 綁定并等待accept到來的連接配接
ChannelFuture f = b.bind(port).sync();
//關閉伺服器
f.channel().closeFuture().sync();
} finally
{
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
其中加入ServerBootstrap中處理channel卻是一個ChannelInitializer ,這是怎麼回事呢,不是應該相應的ChannelHandler嗎?
我們來看一下Channelnitializer源代碼吧
public abstract class ChannelInitializer<C extends Channel> extends ChannelInboundHandlerAdapter {
private static final InternalLogger logger = InternalLoggerFactory.getInstance(ChannelInitializer.class);
/**
* 這個方法會在Channle被注冊時候調用,在方法傳回之後,這個執行個體會在Channel對應的ChannelPipeline中删除
*
* @param ch the {@link Channel} which was registered.
* @throws Exception is thrown if an error occurs. In that case the {@link Channel} will be closed.
*/
protected abstract void initChannel(C ch) throws Exception;
@SuppressWarnings("unchecked")
@Override
public final void channelRegistered(ChannelHandlerContext ctx)
throws Exception {
boolean removed = false;
boolean success = false;
try {
initChannel((C) ctx.channel());
ctx.pipeline().remove(this);
removed = true;
ctx.fireChannelRegistered();
success = true;
} catch (Throwable t) {
logger.warn("Failed to initialize a channel. Closing: " + ctx.channel(), t);
} finally {
if (!removed) {
ctx.pipeline().remove(this);
}
if (!success) {
ctx.close();
}
}
}
}
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiIXZ05WZD9CX5RXa2Fmcn9CXwczLcVmds92czlGZvwVP9EUTDZ0aRJkSwk0LcxGbpZ2LcBDM08CXlpXazRnbvZ2LcRlMMVDT2EWNvwFdu9mZvwVPRpXT5VEVhFDZXpVMo5mYshmMZZXUYpVd1kmYr50MZV3YyI2cKJDT29GRjBjUIF2LcRHelR3LcJzLctmch1mclRXY39DOyMTOwgzMzIDNyITMzEDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
從上面可以看出ChannelInitializer也是一個ChannelHandler,隻是ChannelInitializer的主要任務不是對IO進行處理,而更多的負責對注冊到EventGroup的Channel進行init處理,其中大多是進行加入Handler的處理,也就是上一部落格中我們所看到的加入了一個自定義ChannelHandler
那他是怎麼實作在ChannelInitializer中進行相應的channel的init的呢
他的調用過程這樣的
在這裡請先記得ChannelPipeline、ChannelHandlerContext以及ChannelHandler三者的關系(在以後還會介紹)
是以呢,上面的流程就是在Channel對應的ChannelPipeline中調用它的register方法,再使得channelContextPipeline調用它的相應的register方法,最後才是ChannelInitializer(它也是一個ChannelHandler)
上面流程中在DefaultChannelPipeline中
head是一個ChannelHandlerContext,而我們再看一下DefaultChannelHandlerContext
最後就是我們在上文中ChannelInitializer的代碼了
最後就是我們上一節課例子中的ChannelInitializer内部類在ChannelPipeline中加入新的ChannelContext(對應自定義的ChannelHandler)了
至此,你會發現ChannelHandler是怎麼加入在ChannelPipeline中,對Channel進行處理了