Netty源码分析6-SimpleChannelInboundHandler

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

内容简介:应用中很常见的业务处理情况是等待一种事件发生,然后进行处理。如果使用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);
        }
    }
}

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

查看所有标签

猜你喜欢:

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

算法设计与分析基础

算法设计与分析基础

Anany Levitin / 潘彦 / 清华大学出版社 / 2015-2-1 / 69.00元

作者基于丰富的教学经验,开发了一套全新的算法分类方法。该分类法站在通用问题求解策略的高度,对现有大多数算法准确分类,从而引领读者沿着一条清晰、一致、连贯的思路来探索算法设计与分析这一迷人领域。《算法设计与分析基础(第3版)》作为第3版,相对前版调整了多个章节的内容和顺序,同时增加了一些算法,并扩展了算法的应用,使得具体算法和通用算法设计技术的对应更加清晰有序;各章累计增加了70道习题,其中包括一些......一起来看看 《算法设计与分析基础》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

SHA 加密
SHA 加密

SHA 加密工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器