自定义序列化器
本页介绍如何为你的类型实现自定义序列化器。
基本自定义序列化器
在某些情况下,你可能想为你的类型实现序列化器,特别是对于使用 JDK writeObject/writeReplace/readObject/readResolve 自定义序列化的类,这非常低效。
例如,如果你不想调用以下 Foo#writeObject,你可以实现自定义序列化器:
class Foo {
public long f1;
private void writeObject(ObjectOutputStream s) throws IOException {
System.out.println(f1);
s.defaultWriteObject();
}
}
class FooSerializer extends Serializer<Foo> {
public FooSerializer(Fory fory) {
super(fory, Foo.class);
}
@Override
public void write(MemoryBuffer buffer, Foo value) {
buffer.writeInt64(value.f1);
}
@Override
public Foo read(MemoryBuffer buffer) {
Foo foo = new Foo();
foo.f1 = buffer.readInt64();
return foo;
}
}
注册序列化器
Fory fory = getFory();
fory.registerSerializer(Foo.class, new FooSerializer(fory));
除了注册序列化器,你还可以为类实现 java.io.Externalizable 来自定义序列化逻辑。这种类型将由 Fory 的 ExternalizableSerializer 序列化。
集合序列化器
在为自定义集合类型实现序列化器时,你必须扩展 CollectionSerializer 或 CollectionLikeSerializer。主要区别是 CollectionLikeSerializer 可以序列化具有类似集合结构但不是 Java Collection 子类型的类。
supportCodegenHook 参数
这个特殊参数控制序列化行为:
当为 true 时:
- 启用对集合元素的优化访问和 JIT 编译以获得更好的性能
- 直接序列化调用和内联集合项,无需动态序列化器分派成本
- 对标准集合类型有更好的性能
- 对大多数集合推荐
当为 false 时:
- 使用基于接口的元素访问和元素的动态序列化器分派(成本更高)
- 对自定义集合类型更灵活
- 当集合有特殊序列化需求时需要
- 处理复杂的集合实现
带 JIT 支持的集合序列化器
在实现带 JIT 支持的集合序列化器时,利用 Fory 现有的二进制格式和集合序列化基础设施:
public class CustomCollectionSerializer<T extends Collection> extends CollectionSerializer<T> {
public CustomCollectionSerializer(Fory fory, Class<T> cls) {
// supportCodegenHook 控制是否使用 JIT 编译
super(fory, cls, true);
}
@Override
public Collection onCollectionWrite(MemoryBuffer buffer, T value) {
// 写入集合大小
buffer.writeVarUint32Small7(value.size());
// 写入任何额外的集合元数据
return value;
}
@Override
public Collection newCollection(MemoryBuffer buffer) {
// 创建新的集合实例
Collection collection = super.newCollection(buffer);
// 读取并设置集合大小
int numElements = getAndClearNumElements();
setNumElements(numElements);
return collection;
}
}
注意:在实现 newCollection 时调用 setNumElements,让 Fory 知道要反序列化多少元素。