Netty技术:SimpleChannelInboundHandler<>的使用

简述

在netty中ChannelInboundHandler接口用于处理入站事件,即外部向netty应用程序发起的请求。ChannelInboundHandlerAdapterChannelInboundHandler的实现类,而SimpleChannelInboundHandlerChannelInboundHandlerAdapter的一个子类 SimpleChannelInboundHandler中有一个抽象方法channelRead0(ChannelHandlerContext var1, I var2),SimpleChannelInboundHandler的使用方法便是创建一个具体的处理类,继承SimpleChannelInboundHandler,同时重写channelRead0(ChannelHandlerContext var1, I var2)方法,内部实现具体的处理逻辑(代码块中以NettyRpcClientHandler为例子)

NettyRpcClientHandler 复制代码
public class ChannelInboundHandlerAdapter extends ChannelHandlerAdapter implements ChannelInboundHandler {
......
}
 SimpleChannelInboundHandler<I> extends ChannelInboundHandlerAdapter {
 ......
 }
 
 public class NettyRpcClientHandler extends SimpleChannelInboundHandler<RpcMessage> {    
 private final ConcurrentHashMap<String, CompletableFuture<RpcResponse<Object>>> pendingRequests;
    
    public NettyRpcClientHandler(ConcurrentHashMap<String, CompletableFuture<RpcResponse<Object>>> pendingRequests) {
        this.pendingRequests = pendingRequests;
    }
    //若是消息体的类型是泛型类型RpcMessage便执行channelRead0方法
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, RpcMessage msg) {
        log.debug("Client received message: {}", msg);
        
        if (msg.getMessageType() == RpcMessage.MessageType.RESPONSE.getCode()) {
            RpcResponse<Object> response = (RpcResponse<Object>) msg.getData();
            CompletableFuture<RpcResponse<Object>> future = pendingRequests.remove(response.getRequestId());
            
            if (future != null) {
                future.complete(response);
            } else {
                log.warn("Received response for unknown request: {}", response.getRequestId());
            }
        }
    }
 ......
 }

SimpleChannelInboundHandlerChannelInboundHandlerAdapter 的增强主要体现在三个方面 一、类型匹配和自动类型转换:根据泛型的类型,若是传入的消息体类型为泛型的类型,则将消息体类型转换为泛型的类型,同时执行channelread0方法,若是不符合,执行ctx.fireChannelRead(),将消息题抛给处理器链中的其他处理器处理。

二、自动释放资源:SimpleChannelInboundHandler在处理完消息后,会根据autoRelease属性的值自动释放消息对象占用的资源。这是通过调用ReferenceCountUtil.release(msg)实现的,ChannelInboundHandlerAdapter需要开发者在适当的时候手动释放资源。

三、简化开发流程:SimpleChannelInboundHandler提供了类型匹配、自动类型转换和自动资源释放等功能,它简化了入站消息的处理流程。开发者只需要继承SimpleChannelInboundHandler并实现channelRead0方法即可.

源码解析(看注释)

channelRead(ChannelHandlerContext ctx, Object msg)根据消息体类是否为泛型的类,执行不同方法

channelRead 复制代码
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        //是否进行释放的标记
        boolean release = true;

        try {
        //acceptInboundMessage(msg)判断msg类型是否为泛型类型
            if (this.acceptInboundMessage(msg)) {
                I imsg = msg;//进行类型转换
                this.channelRead0(ctx, imsg);//执行业务处理代码
            } else {
            //标记为不自动释放
                release = false;
                //传递给其他处理器处理
                ctx.fireChannelRead(msg);
            }
        } finally {
            if (this.autoRelease && release) {
            //释放
                ReferenceCountUtil.release(msg);
            }

        }

    }

channelRead0(ChannelHandlerContext ctx, RpcMessage msg)消息处理逻辑

channelRead0 复制代码
    @Override
    //以rpc为例子的channelRead0方法实现
    protected void channelRead0(ChannelHandlerContext ctx, RpcMessage msg) {
        log.debug("Client received message: {}", msg);
        
        if (msg.getMessageType() == RpcMessage.MessageType.RESPONSE.getCode()) {
            RpcResponse<Object> response = (RpcResponse<Object>) msg.getData();
            CompletableFuture<RpcResponse<Object>> future = pendingRequests.remove(response.getRequestId());
            
            if (future != null) {
                future.complete(response);
            } else {
                log.warn("Received response for unknown request: {}", response.getRequestId());
            }
        }
    }

acceptInboundMessage(Object msg)具体判断

acceptInboundMessage 复制代码
//默认构造函数
    protected SimpleChannelInboundHandler() {
        this(true);
    }
//获取对应泛型的类型比较器matcher
    protected SimpleChannelInboundHandler(boolean autoRelease) {
    //具体内部源码看下一个方法源码
        this.matcher = TypeParameterMatcher.find(this, SimpleChannelInboundHandler.class, "I");
        this.autoRelease = autoRelease;
    }
    public boolean acceptInboundMessage(Object msg) throws Exception {
    //返回类判断结果
        return this.matcher.match(msg);
    }
    //具体的matcher类
        private static final class ReflectiveMatcher extends TypeParameterMatcher {
        private final Class<?> type;

        ReflectiveMatcher(Class<?> type) {
            this.type = type;
        }
        //检查对象是否为该泛型类的实例或子类实例
        public boolean match(Object msg) {
            return this.type.isInstance(msg);
        }
    }

find(Object object, Class<?> parametrizedSuperclass, String typeParamName)获取泛型对应的matcher

TypeParameterMatcher中的find()方法 复制代码
public static TypeParameterMatcher find(Object object, Class<?> parametrizedSuperclass, String typeParamName) {
        Map<Class<?>, Map<String, TypeParameterMatcher>> findCache = InternalThreadLocalMap.get().typeParameterMatcherFindCache();
//获取最下层的子类实例的类,也就是NettyRpcClientHandler.getClass;
        Class<?> thisClass = object.getClass();
        //获取以NettyRpcClientHandler。class为key 的matcher存储表
        Map<String, TypeParameterMatcher> map = (Map)findCache.get(thisClass);
        if (map == null) {
            map = new HashMap();
            findCache.put(thisClass, map);
        }
        //获取以泛型参数名typeParamName:'I'为key的存储的matcher
        TypeParameterMatcher matcher = (TypeParameterMatcher)((Map)map).get(typeParamName);
        if (matcher == null) {
        //若是matcher 为空,构建对应的matcher
            matcher = get(find0(object, parametrizedSuperclass, typeParamName));
            ((Map)map).put(typeParamName, matcher);
        }
        //返回matcher
        return matcher;
    }

find0(Object object, Class<?> parametrizedSuperclass, String typeParamName)//获取泛型对应的class

find0 复制代码
   private static Class<?> find0(Object object, Class<?> parametrizedSuperclass, String typeParamName) {
        Class<?> thisClass = object.getClass();
        Class<?> currentClass = thisClass;

        do {
        //获取父类为SimpleChannelInboundHandler的类:currentClass
            while(currentClass.getSuperclass() != parametrizedSuperclass) {
                currentClass = currentClass.getSuperclass();
                if (currentClass == null) {
                    return fail(thisClass, typeParamName);
                }
            }

            int typeParamIndex = -1;
            //获取泛型列表
            TypeVariable<?>[] typeParams = currentClass.getSuperclass().getTypeParameters();
            //typeParamIndex设置为需要的泛型(即'I')在泛型列表中的index
            for(int i = 0; i < typeParams.length; ++i) {
                if (typeParamName.equals(typeParams[i].getName())) {
                    typeParamIndex = i;
                    break;
                }
            }
            //typeParamIndex < 0说明这个泛型不存在于泛型列表
            if (typeParamIndex < 0) {
                throw new IllegalStateException("unknown type parameter '" + typeParamName + "': " + parametrizedSuperclass);
            }
            //获取currentclass的泛型父类,判断是否带有泛型,若是不带有则直接返回Object.class
            Type genericSuperType = currentClass.getGenericSuperclass();
            if (!(genericSuperType instanceof ParameterizedType)) {
                return Object.class;
            }
            //获取泛型列表中,typename为'I'的泛型
            Type[] actualTypeParams = ((ParameterizedType)genericSuperType).getActualTypeArguments();
            Type actualTypeParam = actualTypeParams[typeParamIndex];
            //如果泛型参数本身是一个参数化类型(例如 List<String>),获取其原始类型(List)
            if (actualTypeParam instanceof ParameterizedType) {
                actualTypeParam = ((ParameterizedType)actualTypeParam).getRawType();
            }
            //如果泛型参数是一个具体的类类型(例如 String),直接返回这个类类型
            if (actualTypeParam instanceof Class) {
                return (Class)actualTypeParam;
            }
               //如果泛型参数是一个数组类型(例如 List<String>[]),获取数组的组件类型
            if (actualTypeParam instanceof GenericArrayType) {
                Type componentType = ((GenericArrayType)actualTypeParam).getGenericComponentType();
                //如果组件类型是参数化类型,获取其原始类型
                if (componentType instanceof ParameterizedType) {
                    componentType = ((ParameterizedType)componentType).getRawType();
                }
                //如果组件类型是具体类类型,创建一个空数组并返回其类类型
                if (componentType instanceof Class) {
                    return Array.newInstance((Class)componentType, 0).getClass();
                }
            }
            //如果泛型参数既不是具体类类型,也不是数组类型,那么它可能是一个类型变量(例如 T)如果不是类型变量,调用 fail 方法处理错误
            if (!(actualTypeParam instanceof TypeVariable)) {
                return fail(thisClass, typeParamName);
            }
              //获取类型变量的声明。如果声明不是类类型,返回 Object.class
            TypeVariable<?> v = (TypeVariable)actualTypeParam;
            if (!(v.getGenericDeclaration() instanceof Class)) {
                return Object.class;
            }
            //更新当前类和父类,以便继续解析。
            currentClass = thisClass;
            parametrizedSuperclass = (Class)v.getGenericDeclaration();
            typeParamName = v.getName();
        } while(parametrizedSuperclass.isAssignableFrom(thisClass));

        return Object.class;
    }

TypeParameterMatcher get(Class<?> parameterType)获取对应类的matcher

get 复制代码
    //创建一个默认返回true 的matcher
    private static final TypeParameterMatcher NOOP = new TypeParameterMatcher() {
        public boolean match(Object msg) {
            return true;
        }
    };
    
    public static TypeParameterMatcher get(Class<?> parameterType) {
    //尝试从缓存中获取泛型类对应的matcher
        Map<Class<?>, TypeParameterMatcher> getCache = InternalThreadLocalMap.get().typeParameterMatcherGetCache();
        TypeParameterMatcher matcher = (TypeParameterMatcher)getCache.get(parameterType);
        if (matcher == null) {
            if (parameterType == Object.class) {
            //由于泛型的类是Object,说明所有的类都可以通过matcher的判断,所以直接返回默认返回true的matcher
                matcher = NOOP;
            } else {
            //new一个通过反射判断是否符合泛型类的matcher
                matcher = new ReflectiveMatcher(parameterType);
            }

            getCache.put(parameterType, matcher);
        }

        return (TypeParameterMatcher)matcher;
    }

源码

NettyRpcClientHandler

NettyRpcClientHandler 复制代码
public class NettyRpcClientHandler extends SimpleChannelInboundHandler<RpcMessage> {
    
    private final ConcurrentHashMap<String, CompletableFuture<RpcResponse<Object>>> pendingRequests;
    
    public NettyRpcClientHandler(ConcurrentHashMap<String, CompletableFuture<RpcResponse<Object>>> pendingRequests) {
        this.pendingRequests = pendingRequests;
    }
    
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, RpcMessage msg) {
        log.debug("Client received message: {}", msg);
        
        if (msg.getMessageType() == RpcMessage.MessageType.RESPONSE.getCode()) {
            RpcResponse<Object> response = (RpcResponse<Object>) msg.getData();
            CompletableFuture<RpcResponse<Object>> future = pendingRequests.remove(response.getRequestId());
            
            if (future != null) {
                future.complete(response);
            } else {
                log.warn("Received response for unknown request: {}", response.getRequestId());
            }
        }
    }
    }

SimpleChannelInboundHandler

SimpleChannelInboundHandler 复制代码
    public absSimpleChannelInboundHandlertract class SimpleChannelInboundHandler<I> extends ChannelInboundHandlerAdapter {
    private final TypeParameterMatcher matcher;
    private final boolean autoRelease;

    protected SimpleChannelInboundHandler() {
        this(true);
    }

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

    protected SimpleChannelInboundHandler(Class<? extends I> inboundMessageType) {
        this(inboundMessageType, true);
    }

    protected SimpleChannelInboundHandler(Class<? extends I> inboundMessageType, boolean autoRelease) {
        this.matcher = TypeParameterMatcher.get(inboundMessageType);
        this.autoRelease = autoRelease;
    }

    public boolean acceptInboundMessage(Object msg) throws Exception {
        return this.matcher.match(msg);
    }

    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        boolean release = true;

        try {
            if (this.acceptInboundMessage(msg)) {
                I imsg = msg;
                this.channelRead0(ctx, imsg);
            } else {
                release = false;
                ctx.fireChannelRead(msg);
            }
        } finally {
            if (this.autoRelease && release) {
                ReferenceCountUtil.release(msg);
            }

        }

    }

    protected abstract void channelRead0(ChannelHandlerContext var1, I var2) throws Exception;
}

TypeParameterMatcher

TypeParameterMatcher 复制代码
public abstract class TypeParameterMatcher {
    private static final TypeParameterMatcher NOOP = new TypeParameterMatcher() {
        public boolean match(Object msg) {
            return true;
        }
    };

    public static TypeParameterMatcher get(Class<?> parameterType) {
        Map<Class<?>, TypeParameterMatcher> getCache = InternalThreadLocalMap.get().typeParameterMatcherGetCache();
        TypeParameterMatcher matcher = (TypeParameterMatcher)getCache.get(parameterType);
        if (matcher == null) {
            if (parameterType == Object.class) {
                matcher = NOOP;
            } else {
                matcher = new ReflectiveMatcher(parameterType);
            }

            getCache.put(parameterType, matcher);
        }

        return (TypeParameterMatcher)matcher;
    }

    public static TypeParameterMatcher find(Object object, Class<?> parametrizedSuperclass, String typeParamName) {
        Map<Class<?>, Map<String, TypeParameterMatcher>> findCache = InternalThreadLocalMap.get().typeParameterMatcherFindCache();
        Class<?> thisClass = object.getClass();
        Map<String, TypeParameterMatcher> map = (Map)findCache.get(thisClass);
        if (map == null) {
            map = new HashMap();
            findCache.put(thisClass, map);
        }

        TypeParameterMatcher matcher = (TypeParameterMatcher)((Map)map).get(typeParamName);
        if (matcher == null) {
            matcher = get(find0(object, parametrizedSuperclass, typeParamName));
            ((Map)map).put(typeParamName, matcher);
        }

        return matcher;
    }

    private static Class<?> find0(Object object, Class<?> parametrizedSuperclass, String typeParamName) {
        Class<?> thisClass = object.getClass();
        Class<?> currentClass = thisClass;

        do {
            while(currentClass.getSuperclass() != parametrizedSuperclass) {
                currentClass = currentClass.getSuperclass();
                if (currentClass == null) {
                    return fail(thisClass, typeParamName);
                }
            }

            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;
                }
            }

            if (typeParamIndex < 0) {
                throw new IllegalStateException("unknown type parameter '" + typeParamName + "': " + parametrizedSuperclass);
            }

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

            Type[] actualTypeParams = ((ParameterizedType)genericSuperType).getActualTypeArguments();
            Type actualTypeParam = actualTypeParams[typeParamIndex];
            if (actualTypeParam instanceof ParameterizedType) {
                actualTypeParam = ((ParameterizedType)actualTypeParam).getRawType();
            }

            if (actualTypeParam instanceof Class) {
                return (Class)actualTypeParam;
            }

            if (actualTypeParam instanceof GenericArrayType) {
                Type componentType = ((GenericArrayType)actualTypeParam).getGenericComponentType();
                if (componentType instanceof ParameterizedType) {
                    componentType = ((ParameterizedType)componentType).getRawType();
                }

                if (componentType instanceof Class) {
                    return Array.newInstance((Class)componentType, 0).getClass();
                }
            }

            if (!(actualTypeParam instanceof TypeVariable)) {
                return fail(thisClass, typeParamName);
            }

            TypeVariable<?> v = (TypeVariable)actualTypeParam;
            if (!(v.getGenericDeclaration() instanceof Class)) {
                return Object.class;
            }

            currentClass = thisClass;
            parametrizedSuperclass = (Class)v.getGenericDeclaration();
            typeParamName = v.getName();
        } while(parametrizedSuperclass.isAssignableFrom(thisClass));

        return Object.class;
    }

    private static Class<?> fail(Class<?> type, String typeParamName) {
        throw new IllegalStateException("cannot determine the type of the type parameter '" + typeParamName + "': " + type);
    }

    public abstract boolean match(Object var1);

    TypeParameterMatcher() {
    }

    private static final class ReflectiveMatcher extends TypeParameterMatcher {
        private final Class<?> type;

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

        public boolean match(Object msg) {
            return this.type.isInstance(msg);
        }
    }
}
相关推荐
poemyang3 天前
jemalloc思想的极致演绎:深度解构Netty内存池的精妙设计与实现
rpc·netty
poemyang4 天前
“化零为整”的智慧:内存池如何绕过系统调用和GC,构建性能的护城河
rpc·netty
晓牛开发者5 天前
Netty4 TLS单向安全加密传输案例
netty
hanxiaozhang20187 天前
Netty面试重点-2
面试·netty
9527出列8 天前
Netty源码分析--客户端连接接入流程解析
网络协议·netty
马尚来9 天前
【韩顺平】尚硅谷Netty视频教程
后端·netty
马尚道11 天前
【韩顺平】尚硅谷Netty视频教程
netty
马尚道11 天前
Netty核心技术及源码剖析
源码·netty
moxiaoran575311 天前
java接收小程序发送的protobuf消息
websocket·netty·protobuf