handlerAdded() 方法调用详解
1. ChannelHandlerAdapter 的实现
public class ChannelHandlerAdapter implements ChannelHandler {
// 这个方法有默认实现,是空方法!
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
// 默认什么都不做
}
@Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
// 默认什么都不做
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
ctx.fireExceptionCaught(cause);
}
}
关键点:
ChannelHandlerAdapter不是抽象类,是普通类!- 它提供了
handlerAdded()的默认空实现 - 子类可以选择重写,也可以不重写
2. 继承关系图
ChannelHandler (接口)
↑
ChannelHandlerAdapter (类,提供默认空实现)
↑
ChannelInboundHandlerAdapter (类)
↑
ByteToMessageDecoder (类)
↑
LineBasedFrameDecoder (类)
ChannelHandler (接口)
↑
ChannelHandlerAdapter (类,提供默认空实现)
↑
ChannelInboundHandlerAdapter (类)
↑
MessageToMessageDecoder (类)
↑
StringDecoder (类)
3. 各个类的 handlerAdded() 实现情况
(1) LineBasedFrameDecoder
public class LineBasedFrameDecoder extends ByteToMessageDecoder {
// 没有重写 handlerAdded() 方法
// 使用父类的默认实现
}
(2) ByteToMessageDecoder
public abstract class ByteToMessageDecoder extends ChannelInboundHandlerAdapter {
// 重写了 handlerAdded() 方法!
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
if (ctx.channel().isRegistered()) {
// 如果 channel 已经注册,初始化累加器
if (cumulation == null) {
handlerAdded0(ctx);
}
}
}
protected void handlerAdded0(ChannelHandlerContext ctx) throws Exception { }
}
所以 LineBasedFrameDecoder 调用的是 ByteToMessageDecoder 的 handlerAdded()!
(3) StringDecoder
public class StringDecoder extends MessageToMessageDecoder<ByteBuf> {
// 没有重写 handlerAdded() 方法
// 使用父类的默认实现
}
(4) MessageToMessageDecoder
public abstract class MessageToMessageDecoder<I> extends ChannelInboundHandlerAdapter {
// 没有重写 handlerAdded() 方法
// 使用父类 ChannelInboundHandlerAdapter 的默认实现
}
(5) ChannelInboundHandlerAdapter
public class ChannelInboundHandlerAdapter extends ChannelHandlerAdapter implements ChannelInboundHandler {
// 没有重写 handlerAdded() 方法
// 使用父类 ChannelHandlerAdapter 的默认实现
}
所以 StringDecoder 调用的是 ChannelHandlerAdapter 的空实现!
(6) ChannelInitializer(特殊情况)
public abstract class ChannelInitializer<C extends Channel> extends ChannelInboundHandlerAdapter {
// 重写了 handlerAdded() 方法,这是关键!
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
if (ctx.channel().isRegistered()) {
// 调用 initChannel 方法
if (initChannel(ctx)) {
removeState(ctx);
}
}
}
protected abstract void initChannel(C ch) throws Exception;
}
所以 MyChannelInitializer 调用的是 ChannelInitializer 的 handlerAdded()!
完整的调用链分析
场景:执行 invokeHandlerAddedIfNeeded()
// 假设此时 pipeline 中只有 MyChannelInitializer
Pipeline: head -> MyChannelInitializer -> tail
第一步:触发 MyChannelInitializer.handlerAdded()
invokeHandlerAddedIfNeeded()
↓
callHandlerAdded0(MyChannelInitializer的context)
↓
MyChannelInitializer.handlerAdded() // 实际调用的是父类 ChannelInitializer 的实现
↓
// ChannelInitializer.handlerAdded() 的实现:
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
if (ctx.channel().isRegistered()) {
if (initChannel(ctx)) { // 调用你重写的 initChannel
removeState(ctx);
}
}
}
↓
initChannel(channel) // 你重写的方法
第二步:在 initChannel() 中添加 handlers
protected void initChannel(SocketChannel channel) {
// 1. 添加 LineBasedFrameDecoder
channel.pipeline().addLast(new LineBasedFrameDecoder(1024));
}
addLast() 内部会做什么?
// DefaultChannelPipeline.addLast()
public final ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler) {
final AbstractChannelHandlerContext newCtx;
synchronized (this) {
// 创建新的 context
newCtx = newContext(group, filterName(name, handler), handler);
// 添加到链表中
addLast0(newCtx);
// 关键:如果 pipeline 已经注册,立即调用 handlerAdded
if (registered) {
callHandlerAdded0(newCtx); // ⭐ 这里会调用 handler 的 handlerAdded()
return this;
}
// 如果还没注册,创建待处理任务
callHandlerCallbackLater(newCtx, true);
}
return this;
}
因为此时 pipeline 已经 registered(在 register0 中设置的),所以会立即调用:
callHandlerAdded0(newCtx)
↓
newCtx.callHandlerAdded()
↓
handler().handlerAdded(this) // handler() 返回 LineBasedFrameDecoder 实例
↓
// LineBasedFrameDecoder 没有重写,调用父类 ByteToMessageDecoder 的实现
ByteToMessageDecoder.handlerAdded(ctx)
↓
// ByteToMessageDecoder 的实现:
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
if (ctx.channel().isRegistered()) {
if (cumulation == null) {
handlerAdded0(ctx); // 初始化累加器
}
}
}
第三步:继续添加其他 handlers
// 2. 添加 StringDecoder
channel.pipeline().addLast(new StringDecoder(Charset.forName("GBK")));
↓
callHandlerAdded0(StringDecoder的context)
↓
StringDecoder.handlerAdded(ctx) // 没有重写,调用 ChannelHandlerAdapter 的空实现
↓
// ChannelHandlerAdapter 的实现:
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
// 空方法,什么都不做
}
// 3. 添加 StringEncoder
channel.pipeline().addLast(new StringEncoder(Charset.forName("GBK")));
↓
callHandlerAdded0(StringEncoder的context)
↓
StringEncoder.handlerAdded(ctx) // 没有重写,调用 ChannelHandlerAdapter 的空实现
// 4. 添加 MyServerHandler
channel.pipeline().addLast(new MyServerHandler());
↓
callHandlerAdded0(MyServerHandler的context)
↓
MyServerHandler.handlerAdded(ctx) // 如果你重写了就调用你的,否则调用父类的空实现
总结表格
| Handler 类 | handlerAdded() 实现位置 | 是否有实际逻辑 |
|---|---|---|
| MyChannelInitializer | ChannelInitializer(父类) | ✅ 有,调用 initChannel() |
| LineBasedFrameDecoder | ByteToMessageDecoder(祖父类) | ✅ 有,初始化累加器 |
| StringDecoder | ChannelHandlerAdapter(曾祖父类) | ❌ 空实现 |
| StringEncoder | ChannelHandlerAdapter(曾祖父类) | ❌ 空实现 |
| MyServerHandler | 取决于你是否重写 | 取决于你的实现 |
关键理解
1. ChannelHandlerAdapter 不是抽象类
// 这是一个普通类,提供了默认实现
public class ChannelHandlerAdapter implements ChannelHandler {
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
// 默认空实现,子类可以选择重写
}
}
2. 不是所有 handler 都需要重写 handlerAdded()
大多数 handler 不需要在添加时做特殊处理,所以使用默认空实现就够了。
需要重写的情况:
ChannelInitializer:需要添加其他 handlersByteToMessageDecoder:需要初始化累加器- 你的自定义 handler:如果需要在添加时做初始化
3. 调用链的完整流程
invokeHandlerAddedIfNeeded()
↓
【第一层】触发 MyChannelInitializer.handlerAdded()
↓
调用 initChannel(channel)
↓
【第二层】在 initChannel() 中添加 handlers
↓
pipeline.addLast(new LineBasedFrameDecoder(...))
↓
触发 LineBasedFrameDecoder.handlerAdded()
(实际调用 ByteToMessageDecoder 的实现)
↓
pipeline.addLast(new StringDecoder(...))
↓
触发 StringDecoder.handlerAdded()
(实际调用 ChannelHandlerAdapter 的空实现)
↓
pipeline.addLast(new StringEncoder(...))
↓
触发 StringEncoder.handlerAdded()
(实际调用 ChannelHandlerAdapter 的空实现)
↓
pipeline.addLast(new MyServerHandler())
↓
触发 MyServerHandler.handlerAdded()
(取决于你是否重写)
验证代码
你可以在你的 MyServerHandler 中重写 handlerAdded() 来验证:
public class MyServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
System.out.println("MyServerHandler.handlerAdded() 被调用了!");
super.handlerAdded(ctx); // 调用父类的空实现
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// 你的业务逻辑
}
}
运行后你会看到这个输出,证明 handlerAdded() 确实被调用了!
最终答案
调用的是哪里的 handlerAdded()?
- MyChannelInitializer:调用父类
ChannelInitializer的实现(有实际逻辑) - LineBasedFrameDecoder:调用祖父类
ByteToMessageDecoder的实现(有实际逻辑) - StringDecoder/StringEncoder:调用曾祖父类
ChannelHandlerAdapter的实现(空方法) - MyServerHandler:如果你重写了就调用你的,否则调用父类
ChannelHandlerAdapter的空实现
核心:
ChannelHandlerAdapter提供了默认空实现- 子类可以选择重写,也可以不重写
- 不重写就使用默认空实现,不会报错
- 只有需要在添加时做特殊处理的 handler 才会重写这个方法
906



被折叠的 条评论
为什么被折叠?



