我是一段不羁的公告!
记得给艿艿这 3 个项目加油,添加一个 STAR 噢。
https://github.com/YunaiV/SpringBoot-Labs
https://github.com/YunaiV/onemall
https://github.com/YunaiV/ruoyi-vue-pro

精尽 Netty 源码解析 —— ChannelHandler(三)之 SimpleChannelInboundHandler

1. 概述

在本文,我们来分享 SimpleChannelInboundHandler 处理器。考虑到 SimpleUserEventChannelHandler 和 SimpleChannelInboundHandler 的实现基本一致,所以也会在本文中分享。

如果胖友对 SimpleChannelInboundHandler 的使用不了解,请先看下 《一起学Netty(三)之 SimpleChannelInboundHandler》 ,嘿嘿。

2. SimpleChannelInboundHandler

io.netty.channel.SimpleChannelInboundHandler ,继承 ChannelInboundHandlerAdapter 类,抽象类,处理指定类型的消息。应用程序中,我们可以实现 SimpleChannelInboundHandler 后,实现对指定类型的消息的自定义处理。

2.1 构造方法

public abstract class SimpleChannelInboundHandler<I> extends ChannelInboundHandlerAdapter {

/**
* 类型匹配器
*/
private final TypeParameterMatcher matcher;
/**
* 使用完消息,是否自动释放
*
* @see #channelRead(ChannelHandlerContext, Object)
*/
private final boolean autoRelease;

/**
* see {@link #SimpleChannelInboundHandler(boolean)} with {@code true} as boolean parameter.
*/
protected SimpleChannelInboundHandler() {
this(true);
}

/**
* Create a new instance which will try to detect the types to match out of the type parameter of the class.
*
* @param autoRelease {@code true} if handled messages should be released automatically by passing them to
* {@link ReferenceCountUtil#release(Object)}.
*/
protected SimpleChannelInboundHandler(boolean autoRelease) {
// <1> 获得 matcher
matcher = TypeParameterMatcher.find(this, SimpleChannelInboundHandler.class, "I");
this.autoRelease = autoRelease;
}

/**
* see {@link #SimpleChannelInboundHandler(Class, boolean)} with {@code true} as boolean value.
*/
protected SimpleChannelInboundHandler(Class<? extends I> inboundMessageType) {
this(inboundMessageType, true);
}

/**
* Create a new instance
*
* @param inboundMessageType The type of messages to match
* @param autoRelease {@code true} if handled messages should be released automatically by passing them to
* {@link ReferenceCountUtil#release(Object)}.
*/
protected SimpleChannelInboundHandler(Class<? extends I> inboundMessageType, boolean autoRelease) {
// <2> 获得 matcher
matcher = TypeParameterMatcher.get(inboundMessageType);
this.autoRelease = autoRelease;
}

// ... 省略其它方法
}
  • matcher 属性,有两种方式赋值。
  • autoRelease 属性,使用完消息,是否自动释放。

2.2 acceptInboundMessage

#acceptInboundMessage(Object msg) 方法,判断消息是否匹配。代码如下:

/**
* Returns {@code true} if the given message should be handled. If {@code false} it will be passed to the next
* {@link ChannelInboundHandler} in the {@link ChannelPipeline}.
*/
public boolean acceptInboundMessage(Object msg) {
return matcher.match(msg);
}

一般情况下,matcher 的类型是 ReflectiveMatcher( 它是 TypeParameterMatcher 的内部类 )。代码如下:

private static final class ReflectiveMatcher extends TypeParameterMatcher {

/**
* 类型
*/
private final Class<?> type;

ReflectiveMatcher(Class<?> type) {
this.type = type;
}

@Override
public boolean match(Object msg) {
return type.isInstance(msg); // <1>
}

}
  • 匹配逻辑,看 <1> 处,使用 Class#isInstance(Object obj) 方法。对于这个方法,如果我们定义的 I 泛型是个父类,那可以匹配所有的子类。例如 I 设置为 Object 类,那么所有消息,都可以被匹配列。

2.3 channelRead

 1: @Override
2: public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
3: // 是否要释放消息
4: boolean release = true;
5: try {
6: // 判断是否为匹配的消息
7: if (acceptInboundMessage(msg)) {
8: @SuppressWarnings("unchecked")
9: I imsg = (I) msg;
10: // 处理消息
11: channelRead0(ctx, imsg);
12: } else {
13: // 不需要释放消息
14: release = false;
15: // 触发 Channel Read 到下一个节点
16: ctx.fireChannelRead(msg);
17: }
18: } finally {
19: // 判断,是否要释放消息
20: if (autoRelease && release) {
21: ReferenceCountUtil.release(msg);
22: }
23: }
24: }
  • 第 4 行:release 属性,是否需要释放消息。
  • 第 7 行:调用 #acceptInboundMessage(Object msg) 方法,判断是否为匹配的消息。

    • 匹配,调用 #channelRead0(ChannelHandlerContext ctx, I msg) 抽象方法,处理消息。代码如下:

      /**
      * <strong>Please keep in mind that this method will be renamed to
      * {@code messageReceived(ChannelHandlerContext, I)} in 5.0.</strong>
      *
      * Is called for each message of type {@link I}.
      *
      * @param ctx the {@link ChannelHandlerContext} which this {@link SimpleChannelInboundHandler}
      * belongs to
      * @param msg the message to handle
      * @throws Exception is thrown if an error occurred
      */
      protected abstract void channelRead0(ChannelHandlerContext ctx, I msg) throws Exception;
      • 子类实现 SimpleChannelInboundHandler 类后,实现该方法,就能很方便的处理消息。
    • 不匹配,标记不需要释放消息,并触发 Channel Read 到下一个节点
  • 第 18 至 23 行:通过 release 变量 + autoRelease 属性,判断是否需要释放消息。若需要,调用 ReferenceCountUtil#release(Object msg) 方法,释放消息。😈 还是蛮方便的。

3. SimpleUserEventChannelHandler

io.netty.channel.SimpleUserEventChannelHandler ,继承 ChannelInboundHandlerAdapter 类,抽象类,处理指定事件的消息。

SimpleUserEventChannelHandler 和 SimpleChannelInboundHandler 基本一致,差别在于将指定类型的消息,改成了制定类型的事件。😈 所以,笔者就不详细解析了。

代码如下:

public abstract class SimpleUserEventChannelHandler<I> extends ChannelInboundHandlerAdapter {

/**
* 类型匹配器
*/
private final TypeParameterMatcher matcher;
/**
* 使用完消息,是否自动释放
*
* @see #channelRead(ChannelHandlerContext, Object)
*/
private final boolean autoRelease;

/**
* see {@link #SimpleUserEventChannelHandler(boolean)} with {@code true} as boolean parameter.
*/
protected SimpleUserEventChannelHandler() {
this(true);
}

/**
* Create a new instance which will try to detect the types to match out of the type parameter of the class.
*
* @param autoRelease {@code true} if handled events should be released automatically by passing them to
* {@link ReferenceCountUtil#release(Object)}.
*/
protected SimpleUserEventChannelHandler(boolean autoRelease) {
matcher = TypeParameterMatcher.find(this, SimpleUserEventChannelHandler.class, "I");
this.autoRelease = autoRelease;
}

/**
* see {@link #SimpleUserEventChannelHandler(Class, boolean)} with {@code true} as boolean value.
*/
protected SimpleUserEventChannelHandler(Class<? extends I> eventType) {
this(eventType, true);
}

/**
* Create a new instance
*
* @param eventType The type of events to match
* @param autoRelease {@code true} if handled events should be released automatically by passing them to
* {@link ReferenceCountUtil#release(Object)}.
*/
protected SimpleUserEventChannelHandler(Class<? extends I> eventType, boolean autoRelease) {
matcher = TypeParameterMatcher.get(eventType);
this.autoRelease = autoRelease;
}

/**
* Returns {@code true} if the given user event should be handled. If {@code false} it will be passed to the next
* {@link ChannelInboundHandler} in the {@link ChannelPipeline}.
*/
protected boolean acceptEvent(Object evt) throws Exception {
return matcher.match(evt);
}

@Override
public final void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
// 是否要释放消息
boolean release = true;
try {
// 判断是否为匹配的消息
if (acceptEvent(evt)) {
@SuppressWarnings("unchecked")
I ievt = (I) evt;
// 处理消息
eventReceived(ctx, ievt);
} else {
// 不需要释放消息
release = false;
// 触发 Channel Read 到下一个节点
ctx.fireUserEventTriggered(evt);
}
} finally {
// 判断,是否要释放消息
if (autoRelease && release) {
ReferenceCountUtil.release(evt);
}
}
}

/**
* Is called for each user event triggered of type {@link I}.
*
* @param ctx the {@link ChannelHandlerContext} which this {@link SimpleUserEventChannelHandler} belongs to
* @param evt the user event to handle
*
* @throws Exception is thrown if an error occurred
*/
protected abstract void eventReceived(ChannelHandlerContext ctx, I evt) throws Exception;

}

666. 彩蛋

木有彩蛋,hoho 。

总访客数 && 总访问量