Netty源码分析6-SimpleChannelInboundHandler

栏目: 编程工具 · 发布时间: 5年前

内容简介:应用中很常见的业务处理情况是等待一种事件发生,然后进行处理。如果使用ChannelInboundHandler则需要这样做。这样的代码需要重复很多地方,有没有一种通用的处理方式呢,这就是SimpleChannelInboundHandler了。这种方式不再需要instanceof判断、强制类型转换等重复操作。一个需要注意的地方是SimpleChannelInbound会在channelRead0后默认对msg进行release,即refCnt减一,这个可以通过构造函数autoRelease参数来控制。

应用中很常见的业务处理情况是等待一种事件发生,然后进行处理。如果使用ChannelInboundHandler则需要这样做。

public class FooHandlerextends ChannelInboundHandlerAdapter{
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg instanceof Foo) {
            Foo foo = (Foo) msg;
            // do something
        } else {
            super.channelRead(ctx, msg);
        }
    }
}

这样的代码需要重复很多地方,有没有一种通用的处理方式呢,这就是SimpleChannelInboundHandler了。这种方式不再需要instanceof判断、强制类型转换等重复操作。

一个需要注意的地方是SimpleChannelInbound会在channelRead0后默认对msg进行release,即refCnt减一,这个可以通过构造函数autoRelease参数来控制。

public class FooHandlerextends SimpleChannelInboundHandler<Foo>{
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, Foo foo) throws Exception {
        // do something
    }
}

SimpleChannelInboundHandler实现分析

要实现SimpleChannelInboundHandler的功能,主要要能够得到应用中声明的泛型信息,Java中获得泛型信息一般是通过genericSuperclass来获取,例如要获取ArrayList

的泛型信息String,需要这样。

((ParameterizedType)(new ArrayList<String>(){}.getClass().getGenericSuperclass())).getActualTypeArguments()[0]

还有一些其他的case要处理,例如多个泛型信息等。Netty将这些封装到了一个TypeParameterMatcher类中,方便类似判断一个对象是否是类的泛型类的对象。

这个类的主要工作在一个find0方法上,通过一个对象和它的参数化父类和一个具体类的字符串名来找到这个类。

SimpleChannelInboundHandler的构造方法中首先通过SimpleChannelInboundHandler类和”I”作为参数构造一个TypeParameterMatcher,

这样继承SimpleChannelInboundHandler就可以得到具体的I的实现了。

public abstract class SimpleChannelInboundHandler<I>extends ChannelInboundHandlerAdapter{

    private final TypeParameterMatcher matcher;
    private final boolean autoRelease;
    protected SimpleChannelInboundHandler(boolean autoRelease) {
        matcher = TypeParameterMatcher.find(this, SimpleChannelInboundHandler.class, "I");
        this.autoRelease = autoRelease;
    }

而在channelRead中通过判断msg是否属于”T”这个具体类来决定是否要调用需要子类override的channelRead0方法。

并且在最后通过判断autoRelease参数来决定是否要对msg的refCnt减一。

@Override
public void channelRead(ChannelHandlerContext ctx, Object msg)throws Exception {
    boolean release = true;
    try {
        if (acceptInboundMessage(msg)) {
            @SuppressWarnings("unchecked")
            I imsg = (I) msg;
            channelRead0(ctx, imsg);
        } else {
            release = false;
            ctx.fireChannelRead(msg);
        }
    } finally {
        if (autoRelease && release) {
            ReferenceCountUtil.release(msg);
        }
    }
}
protected abstract void channelRead0(ChannelHandlerContext ctx, I msg)throws Exception;

而TypeParameter是如何获取到”I”的类型的呢

下面代码省略了一些异常或其他特殊判断,也是通过getGenericSuperclass和getTypeParameters来得到的。

private static Class<?> find0(
        final Object object, Class<?> parametrizedSuperclass, String typeParamName) {

    final Class<?> thisClass = object.getClass();
    Class<?> currentClass = thisClass;
    for (;;) {
        if (currentClass.getSuperclass() == parametrizedSuperclass) {
            int typeParamIndex = -1;
            TypeVariable<?>[] typeParams = currentClass.getSuperclass().getTypeParameters();
            for (int i = 0; i < typeParams.length; i ++) {
                if (typeParamName.equals(typeParams[i].getName())) {
                    typeParamIndex = i;
                    break;
                }
            }

           TypegenericSuperType = currentClass.getGenericSuperclass();
            if (!(genericSuperType instanceof ParameterizedType)) {
                return Object.class;
            }

            Type[] actualTypeParams = ((ParameterizedType) genericSuperType).getActualTypeArguments();

           TypeactualTypeParam = actualTypeParams[typeParamIndex];
            if (actualTypeParam instanceof ParameterizedType) {
                actualTypeParam = ((ParameterizedType) actualTypeParam).getRawType();
            }
            if (actualTypeParam instanceof Class) {
                return (Class<?>) actualTypeParam;
            }
            ...
        }
        currentClass = currentClass.getSuperclass();
        if (currentClass == null) {
            return fail(thisClass, typeParamName);
        }
    }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

图解服务器端网络架构

图解服务器端网络架构

[日] 宫田宽士 / 曾薇薇 / 人民邮电出版社 / 2015-4 / 79.00元

本书以图配文,详细说明了服务器端网络架构的基础技术和设计要点。基础设计是服务器端网络架构最重要的一个阶段。本书就立足于基础设计的设计细分项目,详细介绍各细分项目的相关技术和设计要点。全书共分为5章,分别讲述进行物理设计、逻辑设计、安全设计和负载均衡设计、高可用性设计以及管理设计时所必需的技术和设计要点。一起来看看 《图解服务器端网络架构》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

html转js在线工具
html转js在线工具

html转js在线工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具