在上一篇博客中,我们看到例子中有一段代码
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();
}
}
}
}
从上面可以看出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进行处理了