2021SC@SDUSC
一、代码分析内容
本次博客介绍core-serializer包中的stream包。stream包就是serializer模块中关于数据流的这一部分。下面我们可以通过查看stream包的结构,来得知它是和那些数据流相关的。
二、stream包结构
我们从图中可以看出,stream包中的类大致可以分为三类。其中DiffStreamCodec、DiffStreamDecoder、DiffStreamEncoder为一类,它们是扩散流编码译码器、扩散流解码器、扩散流编码器;StreamCodec、StreamCodecFactory、StreamCodecRegistry、StreamCodecs、StreamDecoder、StreamEncoder为一类,它们是有关流编码、解码的;StreamInput、StreamOutput为一类,它们是有关流输入输出的。
三、代码解读
我们分成三类来看,就是上面提到的三类。
第一类:
1.DiffStreamDecoder类
此类是一个接口,它的作用就是对输入流进行扩散解码。可以看到定义的接口中,decodeDiff方法input参数的对象是StreamInput ,可以说明它的作用就是对输入流进行操作的。
public interface DiffStreamDecoder<T> {
T decodeDiff(StreamInput input, T from) throws IOException;
}
2.DiffStreamEncoder类
此类也是一个接口,它和DiffStreamDecoder类是类似的。它是输入流进行扩散编码。
public interface DiffStreamEncoder<T> {
void encodeDiff(StreamOutput output, T from, T to) throws IOException;
}
3.DiffStreamCodec类
这个类也是一个接口,它继承了DiffStreamEncoder接口、DiffStreamDecoder接口和StreamCodec接口。其中两个是我们上面说过的,StreamCodec接口会在下面介绍。它继承这几个接口,说明它是一个有着集成性质的编码译码器。
public interface DiffStreamCodec<T> extends StreamCodec<T>, DiffStreamEncoder<T>, DiffStreamDecoder<T> {
}
第二类:
4.StreamEncoder类
这个接口定义的方法encode是对输出流进行编码,和DiffStreamEncoder类中那个方法类似。
public interface StreamEncoder<T> {
void encode(StreamOutput output, T item) throws IOException;
}
5.StreamDecoder类
这个接口定义的方法是对输入流进行解码。
public interface StreamDecoder<T> {
T decode(StreamInput input) throws IOException;
}
6.StreamCodec类
这个类的性质DiffStreamCodec类一样,都是继承了编码和解码的。StreamCodec集成了StreamEncoder和StreamDecoder,但它对集成的这两个类的方法进行了重写。
static <T> StreamCodec<T> of(StreamEncoder<? super T> encoder, StreamDecoder<? extends T> decoder) {
return new StreamCodec<T>() {
@Override
public void encode(StreamOutput output, T item) throws IOException {
encoder.encode(output, item);
}
@Override
public T decode(StreamInput input) throws IOException {
return decoder.decode(input);
}
};
}
static <T> StreamCodec<T> of(BinarySerializer<T> binarySerializer) {
return new StreamCodec<T>() {
@Override
public void encode(StreamOutput output, T item) throws IOException {
output.serialize(binarySerializer, item);
}
@Override
public T decode(StreamInput input) throws IOException {
return input.deserialize(binarySerializer);
}
};
}
7.StreamCodecFactory类
这是一个可以为给定类型创建或检索编解码器的接口。
public interface StreamCodecFactory {
default <T> StreamCodec<T> get(Class<T> type) {
return get((Type) type);
}
default <T> StreamCodec<T> get(TypeT<T> type) {
return get(type.getType());
}
<T> StreamCodec<T> get(Type type);
}
8.StreamCodecRegistry类
此类是按编解码器类型存储编解码器并允许动态调度编解码器的注册表。它还允许为泛型类型动态构造编解码器。
此类implements的是StreamCodecFactory类和 WithInitializer类。StreamCodecFactory类是上面提到的,WithInitializer类是codegen模块中的,它的作用是with初始化器。在StreamCodecRegistry类中定义with方法时有用到。
create()方法:
此方法创建一个新的完全空的注册表。建议改用createDefault()工厂方法。
public static StreamCodecRegistry create() {
return new StreamCodecRegistry();
}
createDefault()方法:
此方法创建一个带有一组默认编解码器(原语、一些Java类型和集合)的注册表。下面我列举部分:
public static StreamCodecRegistry createDefault() {
return create()
.with(void.class, ofVoid())
.with(boolean.class, ofBoolean())
.with(char.class, ofChar())
.with(byte.class, ofByte())
.with(int.class, ofInt())
.with(long.class, ofLong())
.with(float.class, ofFloat())
.with(double.class, ofDouble())
}
第三类:
9.StreamInput类
这个类在上面都是以方法的参数形式出现的。它就是定义的输入流,我们先来看一下它定义的属性。它定义了缓存长度、二进制输入、限制、输入流、长度为128的char数组。
public static final int DEFAULT_BUFFER_SIZE = 16384;
private BinaryInput in;
private int limit;
private final InputStream inputStream;
private char[] charArray = new char[128];
从构造方法可以看出,给输入的二进制分配了一个初始化的缓存大小。
private StreamInput(InputStream inputStream, int initialBufferSize) {
this.inputStream = inputStream;
this.in = new BinaryInput(allocate(initialBufferSize));
}
此类定义了一系列read方法,用以来适应各种数据类型。
public final int read(byte[] b) throws IOException {
return read(b, 0, b.length);
}
public final int read(byte[] b, int off, int len) throws IOException {
ensure(len);
in.read(b, off, len);
return len;
}
public final byte readByte() throws IOException {
return in.pos < limit ? in.readByte() : readByteImpl();
}
private byte readByteImpl() throws IOException {
doEnsureRead(1);
return in.readByte();
}
10.StreamOutput类
这个方法从方向上看,正好和StreamInput类相反,结构和StreamInput类是一样的。可以从它定义的属性和构造函数看得出来。
private static final int MAX_SIZE = 1 << 28; // 256MB
public static final int DEFAULT_BUFFER_SIZE = 16384;
private BinaryOutput out;
private final OutputStream outputStream;
private int estimatedDataSize = 1;
private int estimatedHeaderSize = 1;
private StreamOutput(OutputStream outputStream, int initialBufferSize) {
this.outputStream = outputStream;
this.out = new BinaryOutput(allocate(initialBufferSize));
}
同样此类定义了一系列write方法,用以来适应各种数据类型。
public final void write(byte[] b) throws IOException {
ensure(b.length);
out.write(b);
}
public final void write(byte[] b, int off, int len) throws IOException {
ensure(len);
out.write(b, off, len);
}
public final void writeBoolean(boolean v) throws IOException {
ensure(1);
out.writeBoolean(v);
}
public final void writeByte(byte v) throws IOException {
if (out.pos() < out.array().length) {
out.writeByte(v);
} else {
writeByteImpl(v);
}
}
四、总结
本次分析的代码是stream包中的10个类,这个包是有关数据流输入、输出、解码、编码的。很明显这个在序列化中是非常重要的。