Netty源碼分析-MessageToByteEncoder

MessageToByteEncoder是一個抽象編碼器,子類可重新encode方法把對象編碼爲ByteBuf輸出。

 

源碼分析


package io.netty.handler.codec;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOutboundHandler;
import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.ChannelPromise;
import io.netty.util.ReferenceCountUtil;
import io.netty.util.internal.TypeParameterMatcher;


public abstract class MessageToByteEncoder<I> extends ChannelOutboundHandlerAdapter {

    private final TypeParameterMatcher matcher;
    private final boolean preferDirect;

   
    protected MessageToByteEncoder() {
        this(true);
    }

    //匹配msg的數據類型是否爲I,也就是子類定義的泛型
    public boolean acceptOutboundMessage(Object msg) throws Exception {
        return matcher.match(msg);
    }

    @Override
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
        ByteBuf buf = null;
        try {
            //msg是I這種類型就調用編碼邏輯,否則向下傳遞
            if (acceptOutboundMessage(msg)) {
                @SuppressWarnings("unchecked")
                I cast = (I) msg; //類型轉換
                //分配ByteBuf,默認堆外類型
                buf = allocateBuffer(ctx, cast, preferDirect);
                try {
                    //子類實現編碼邏輯
                    encode(ctx, cast, buf);
                } finally {
                    //釋放msg
                    ReferenceCountUtil.release(cast);
                }

                //如果buf可讀,則寫入ctx,實際就是交給netty調用底層socket輸出
                if (buf.isReadable()) {
                    ctx.write(buf, promise);
                } else {
                    //否則釋放buf
                    buf.release();
                    //向下傳遞空的buf對象
                    ctx.write(Unpooled.EMPTY_BUFFER, promise);
                }
                buf = null;
            } else {
                //如果不是I類型,則次編碼器不做任何處理,直接傳遞msg對象給下一個編碼器
                ctx.write(msg, promise);
            }
        } catch (EncoderException e) {
            throw e;
        } catch (Throwable e) {
            throw new EncoderException(e);
        } finally {
            if (buf != null) {
                buf.release();
            }
        }
    }

   
    protected ByteBuf allocateBuffer(ChannelHandlerContext ctx, @SuppressWarnings("unused") I msg,
                               boolean preferDirect) throws Exception {
        if (preferDirect) {
            return ctx.alloc().ioBuffer();
        } else {
            return ctx.alloc().heapBuffer();
        }
    }

    
    //需要子類實現,根據msg的內容,把數據寫入ByteBuf中
    protected abstract void encode(ChannelHandlerContext ctx, I msg, ByteBuf out) throws Exception;

    //默認使用堆外內存
    protected boolean isPreferDirect() {
        return preferDirect;
    }
}

 

例子,一個Integer類型的編碼,負責把一個Integer寫入到ByteBuf當中。

public class IntegerEncoder extends MessageToByteEncoder<Integer> {
          @Override
         public void encode(ChannelHandlerContext ctx, Integer msg, ByteBuf out)
                 throws Exception {
             out.writeInt(msg);
         }
     }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章