2021SC@SDUSC
一、代码分析内容
本次博客继续进行core-serializer包中imp包的分析,上一次分析了这个包的六个序列化定义的几个数据结构的类,本次我们再来分析一下剩下的7个类,它们是定义的其他一些数据结构的序列化定义。
二、impl包结构
本次分析的是SerializerDefClass类、SerializerDefCollection类、SerializerDefDouble类、SerializerDefEnum类、SerializerDefFloat类、SerializerDefInet4Address类、SerializerDefInet6Address类这7个类。
三、代码解读
1.SerializerDefClass类
此类继承AbstractSerializerDef类,这个是序列化定义类的类,说起来就像是套娃一样。从这个名字可以看出,这个类中要包含Class的一些功能,要将这些都进行Serialize操作。下面我们来看一下。此类定义的属性如下:
private final Class<?> encodeType;
private final Class<?> decodeType;
private final LinkedHashMap<String, FieldDef> fields = new LinkedHashMap<>();
private Constructor<?> constructor;
private List<String> constructorParams;
private Method factory;
private List<String> factoryParams;
private final Map<Method, List<String>> setters = new LinkedHashMap<>();
private SerializerDefClass(Class<?> encodeType, Class<?> decodeType) {
this.encodeType = encodeType;
this.decodeType = decodeType;
}
这里定义了encodeType、decodeType这两个编码和解码类型,下面这两个属性是要用到的。
我们看到constructor属性就是构造器,是进行要对构造方法的形式进行改变的。下面的constructorParams列表就是存储constructor的各种参数。
factory是工厂方法,它也有一个参数列表factoryParams。
下面是create方法,其作用是创建一个class所用的:
public static SerializerDefClass create(@NotNull Class<?> type) {
return new SerializerDefClass(type, type);
}
public static SerializerDefClass create(@NotNull Class<?> encodeType, @NotNull Class<?> decodeType) {
if (!encodeType.isAssignableFrom(decodeType))
throw new IllegalArgumentException(format("Class should be assignable from %s", decodeType));
return new SerializerDefClass(encodeType, decodeType);
}
下面几个方法就是对上述定义的属性进行的操作,当然,也是一个class所必需的。例如Setter和Getter方法等:
public void addSetter(@NotNull Method method, @NotNull List<String> fields) {
if (decodeType.isInterface())
throw new IllegalStateException("Class should either implement an interface or be an interface");
if (isPrivate(method.getModifiers()))
throw new IllegalArgumentException(format("Setter cannot be private: %s", method));
if (method.getGenericParameterTypes().length != fields.size())
throw new IllegalArgumentException("Number of arguments of a method should match a size of list of fields");
if (setters.containsKey(method)) throw new IllegalArgumentException("Setter has already been added");
setters.put(method, fields);
}
public void addGetter(Method method, SerializerDef serializer, int added, int removed) {
if (method.getGenericParameterTypes().length != 0)
throw new IllegalArgumentException("Method should have 0 generic parameter types");
if (!isPublic(method.getModifiers()))
throw new IllegalArgumentException("Method should be public");
String fieldName = stripGet(method.getName(), method.getReturnType());
if (fields.containsKey(fieldName)) throw new IllegalArgumentException(format("Duplicate field '%s'", method));
FieldDef fieldDef = new FieldDef();
fieldDef.method = method;
fieldDef.serializer = serializer;
fieldDef.versionAdded = added;
fieldDef.versionDeleted = removed;
fields.put(fieldName, fieldDef);
}
public void setConstructor(@NotNull Constructor<?> constructor, @NotNull List<String> fields) {
if (decodeType.isInterface())
throw new IllegalStateException("Class should either implement an interface or be an interface");
if (this.constructor != null)
throw new IllegalArgumentException(format("Constructor is already set: %s", this.constructor));
if (isPrivate(constructor.getModifiers()))
throw new IllegalArgumentException(format("Constructor cannot be private: %s", constructor));
if (constructor.getGenericParameterTypes().length != fields.size())
throw new IllegalArgumentException("Number of arguments of a constructor should match a size of list of fields");
this.constructor = constructor;
this.constructorParams = fields;
}
当然这个类里面也有专属于它的编码和解码方法。
2.SerializerDefCollection类
此类继承AbstractSerializerDefCollection类,AbstractSerializerDefCollection类是一个序列化定义Collection的类的一个抽象类,它的构造方法和重写方法如下:
public SerializerDefCollection(SerializerDef valueSerializer, Class<?> encodeType, Class<?> decodeType) {
this(valueSerializer, encodeType, decodeType, false);
}
private SerializerDefCollection(SerializerDef valueSerializer, Class<?> encodeType, Class<?> decodeType, boolean nullable) {
super(valueSerializer, Collection.class, decodeType, Object.class, nullable);
}
@Override
public SerializerDef ensureNullable(CompatibilityLevel compatibilityLevel) {
if (compatibilityLevel.getLevel() < LEVEL_3.getLevel()) {
return new SerializerDefNullable(this);
}
return new SerializerDefCollection(valueSerializer, encodeType, decodeType, true);
}
这里重写的是ensureNullable方法,它是在ensureNullable类中出现的,而AbstractSerializerDefCollection类实现了ensureNullable类。
3.SerializerDefDouble类
此类继承了SerializerDefPrimitive类,这是上一次博客分析过的序列化定义原语的类。此类中ensureWrapped,doSerialize和doDeserialize方法都是继承自SerializerDefPrimitive类并且进行重写的。是为了定义有关Double的。doSerialize方法就是进行writeDouble,doDeserialize方法就是进行readDouble的。
public SerializerDefDouble() {
this(true);
}
public SerializerDefDouble(boolean wrapped) {
super(double.class, wrapped);
}
@Override
public SerializerDef ensureWrapped() {
return new SerializerDefDouble(true);
}
@Override
protected Expression doSerialize(Expression byteArray, Variable off, Expression value, CompatibilityLevel compatibilityLevel) {
return writeDouble(byteArray, off, value, !compatibilityLevel.isLittleEndian());
}
@Override
protected Expression doDeserialize(Expression in, CompatibilityLevel compatibilityLevel) {
return readDouble(in, !compatibilityLevel.isLittleEndian());
}
4.SerializerDefFloat类
这个类和上面的SerializerDefDouble类还是比较相似的,因为float和double都是基本的数据类型,所以序列化还是相对来说比较简单的。也就是在doSerialize和doDeserialize方法中使用的writeFloat和readFloat的不同。
public SerializerDefFloat() {
this(true);
}
public SerializerDefFloat(boolean wrapped) {
super(float.class, wrapped);
}
@Override
public SerializerDef ensureWrapped() {
return new SerializerDefFloat(true);
}
@Override
protected Expression doSerialize(Expression byteArray, Variable off, Expression value, CompatibilityLevel compatibilityLevel) {
return writeFloat(byteArray, off, value, !compatibilityLevel.isLittleEndian());
}
@Override
protected Expression doDeserialize(Expression in, CompatibilityLevel compatibilityLevel) {
return readFloat(in, !compatibilityLevel.isLittleEndian());
5.SerializerDefEnum类
这是一个序列化定义枚举类型的类。枚举类型我们平时用的比较少,这个类继承AbstractSerializerDef类和SerializerDefWithNullable类。我们通过它定义的属性和构造方法中可以看出,它定义了枚举类型和是否可为空。
private final Class<? extends Enum<?>> enumType;
private final boolean nullable;
public SerializerDefEnum(Class<? extends Enum<?>> enumType, boolean nullable) {
this.enumType = enumType;
this.nullable = nullable;
}
下面是isSmallEnum方法,这个方法在此类的encoder和decoder方法中都有使用到。这个方法返回了Enum的大小,就像它的方法名一样,是一个小的枚举,我们可以看到,如果size >= 16384,就会抛出异常。
private boolean isSmallEnum() {
int size = enumType.getEnumConstants().length + (nullable ? 1 : 0);
if (size >= 16384) throw new IllegalArgumentException();
return size <= Byte.MAX_VALUE;
}
6.SerializerDefInet4Address类
Inet4Address这个类是InetAddress的子类,它是java中有关IPv4的类。而SerializerDefInet4Address类就是序列化定义Inet4Address的。在getEncodeType方法中,返回的就是Inet4Address.class,而编码和解码方法是对读写字节进行处理,调用地址。
@Override
public Class<?> getEncodeType() {
return Inet4Address.class;
}
@Override
public Expression encoder(StaticEncoders staticEncoders, Expression buf, Variable pos, Expression value, int version, CompatibilityLevel compatibilityLevel) {
return writeBytes(buf, pos, call(value, "getAddress"));
}
@Override
public Expression decoder(StaticDecoders staticDecoders, Expression in, int version, CompatibilityLevel compatibilityLevel) {
return let(arrayNew(byte[].class, value(4)), array ->
sequence(
readBytes(in, array),
staticCall(getDecodeType(), "getByAddress", array)));
}
7.SerializerDefInet6Address
这是有关IPv6的,和上面那个类基本一致,就是在decoder的let(arrayNew(byte[].class, value(16)),
中value参数不一样。
public Expression decoder(StaticDecoders staticDecoders, Expression in, int version, CompatibilityLevel compatibilityLevel) {
return let(arrayNew(byte[].class, value(16)), array ->
sequence(
readBytes(in, array),
staticCall(getDecodeType(), "getByAddress", nullRef(String.class), array, nullRef(NetworkInterface.class))));
}
四、总结
本次博客分析的是impl的另外7个类,我认为上述的这几个类中,SerializerDefClass类是最重要的,因为它的层次是比较高的,而其他的几个就是定义一些数据类型。