netty中Channel, ChannelPipeline, ChannelHandler, ChannelHandlerContext 的关系
一:channel 和 pipeline 一一对应的
channel 和 pipeline 一一对应的。创建channel时,同时创建pipeline。共生攻灭
pipeline是channel的属性
// pipeline是channel的属性
private final DefaultChannelPipeline pipeline;
protected AbstractChannel(Channel parent) {
this.parent = parent;
id = newId();
unsafe = newUnsafe();
// 创建channel时,同时创建pipeline
pipeline = newChannelPipeline();
}
二:pipeline 串起的其实是ctx
所有文档都说pipeline串起多个handler。pipeline确实是串起多个handler,但,具体到实际代码,pipeline 串起的其实是ctx。
ctx是pipeline的属性(pipeline中双向链表的头元素、中间元素、尾元素);
即:pipeline中有两个属性head和tail,都是ctx,所以pipeline存储了一个双向链表,链表的head, tail都是ctx,链表中的元素当然也是ctx。所以说pipeline串起的是ctx(而不是handler哦。)
不过呢,被串起的ctx中有个属性是handler。所以说:pipeline串起ctx,其实也就是 pipeline串起了handler。
// ctx是pipeline 的属性(head, tail都是ctx)
final AbstractChannelHandlerContext head;
final AbstractChannelHandlerContext tail;
protected DefaultChannelPipeline(Channel channel) {
this.channel = ObjectUtil.checkNotNull(channel, "channel");
succeededFuture = new SucceededChannelFuture(channel, null);
voidPromise = new VoidChannelPromise(channel, true);
tail = new TailContext(this);
head = new HeadContext(this);
head.next = tail;
tail.prev = head;
}
// ctx中有个属性是handler。所以
// pipeline串起ctx,其实也就是串起了handler
DefaultChannelHandlerContext(
DefaultChannelPipeline pipeline, EventExecutor executor, String name, ChannelHandler handler) {
super(pipeline, executor, name, handler.getClass());
this.handler = handler;
}
三:同一个handler实例 可以被加进多个pipeline(每次加入得到一个新的ctx实例)
每当将handler实例加进pipeline,就创建了ctx,并且将该ctx加入了pipeline。
这太容易理解了,新创建网络连接即channel(也就创建了pipeline)时,我们总是要给每一个channel(的pipeline)添加handler的,handler是用来处理该网络连接上的数据的。
同一个handler实例可以被加进多个pipeline(so创建了多个ctx),channel毁灭(pipeline也同时毁灭),但handler实例可以继续存在,因为handler实例 还位于别的 pipeline中啊。
// handler被加入了pipeline
// 此时,生成了新的ctx,即下面的newCtx
public final ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler) {
final AbstractChannelHandlerContext newCtx;
synchronized (this) {
checkMultiplicity(handler);
// 加handler进入pipeline时,就返回了ctx
newCtx = newContext(group, filterName(name, handler), handler);
addLast0(newCtx);
// If the registered is false it means that the channel was not registered on an eventLoop yet.
// In this case we add the context to the pipeline and add a task that will call
// ChannelHandler.handlerAdded(...) once the channel is registered.
if (!registered) {
newCtx.setAddPending();
callHandlerCallbackLater(newCtx, true);
return this;
}
EventExecutor executor = newCtx.executor();
if (!executor.inEventLoop()) {
callHandlerAddedInEventLoop(newCtx, executor);
return this;
}
}
callHandlerAdded0(newCtx);
return this;
}
四:举个例子
假设
有两个@ChannelHandler.Sharable的 ChannelHandler类,AuthHandler, RemoveSensitiveWordHandler;
要创建两个网络连接即两个channel
public class XXXSocketServerInitializer extends ChannelInitializer<SocketChannel> {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new AuthHandler(false));
pipeline.addLast(new RemoveSensitiveWordHandler());
}
}
创建完成2个网络连接即两个channel假设channel1, channel2之后,我们得到的实例是这样的:
1. 两个 Channel 的实例,即:channel1, channel2
2. 两个 ChannelPipeline 的实例,即:pipeline1, pipeline2。它们和各自的channel共生攻灭
3. 两个ChannelHandler都是@ChannelHandler.Sharable,它们都永远各自只有一个实例,假设它们是:authHandler1, rmvWordHandler1
4. 几个ctx呢?每次加入pipeline都会新建ctx,因此,4个ctx。具体即:
对于pipeline1
pipeline1.addLast(authHandler1)时,得到了 ctx1_1
pipeline1.addLast(rmvWordHandler1)时,得到了 ctx1_2
于是,pipeline1存储的是:new DefaultChannelPipeline.HeadContext()--> ctx1_1--> ctx1_2--> new DefaultChannelPipeline.TailContext()
对于pipeline2
pipeline2.addLast(authHandler1)时,得到了 ctx2_1
pipeline2.addLast(rmvWordHandler1)时,得到了 ctx2_2
于是,pipeline2存储的是:new DefaultChannelPipeline.HeadContext()--> ctx2_1--> ctx2_2--> new DefaultChannelPipeline.TailContext()
完