Kryo中的序列化事件

时间:2012-09-07 21:03:27

标签: kryo

您如何收到序列化事件?你可以定义

void writeObject(ObjectOutputStream out) {
  // handle event
  out.defaultWriteObject(this);
}

在java序列化中,当您的对象被序列化时,将调用此方法。你怎么在Kryo做同样的事情? KryoSerializableExternalizable都存在默认序列化的问题:一旦调用了事件处理程序,就需要默认的读/写对象。但是没有这样的事情! ?您可以在FieldSerializer中调用read(Kryo, Input)来读取对象的字段,但它会生成一个新对象而不是填充当前对象。出于这个原因,我尝试引入自定义序列化器:

Serializer def = kryo.getDefaultSerializer(A.class)
kryo.addDefaultSerializer(A.class, new Serializer() {
    public void write(Kryo kryo, Output output, Object object) {
        ((A)object).serializationEvent();
        def.write(kryo, output, object);

但是,我提到通过A的子类接收serializationEvent()事件,只有A.class字段被序列化。因此,这对class B extends A不起作用。我还尝试了解决方案proposed by Natanregister(A.class, new FieldSerializer(A.class, myhandler。这会序列化所有字段,包括子类,但根本不会为子类调用自定义序列化程序。因此,我认为Kryo定制仅适用于最终课程。 Nathan says that this conclusion is "invalid" and KryoSerializable solution "application-specific" and thinking otherwise "rude".尽管有这样的解决方案,我还是决定发布我发现的一般方法。

1 个答案:

答案 0 :(得分:1)

我发现了两种解决方案。首先,重写writeReferenceOrNull可以工作

Kryo kryo = new Kryo() {
    public boolean writeReferenceOrNull (Output output, Object object, boolean mayBeNull) {
        if (object instanceof A) {
            ((A) object).serializationEvent();
        }

        return super.writeReferenceOrNull(output, object, mayBeNull);
    }

但是,它需要源代码可见性更改,Natan说只有在启用引用时才会起作用(在默认情况下)并建议采用更可靠的方法:覆盖newDefaultSerializer:

public class EventFiringKryo extends Kryo {
    protected Serializer newDefaultSerializer(Class type) {
        final Serializer def = super.newDefaultSerializer(type);
        Serializer custom = new Serializer() {

            public void write(Kryo kryo, Output output, Object object) {
                System.err.println("writing " + object + ":" + object.getClass().getSimpleName());
                if (object instanceof A)
                    ((A)object).serializationEvent();
                def.write(kryo, output, object);
            }

            public Object read(Kryo kryo, Input input, Class type) {
                Object result = def.read(kryo, input, type);
                if (result instanceof SomeAnotherType)
                    result.canInitializeSomethingElse();
                return result;
            }
        };
        return custom;
    }

}

除了有效之外,此方法不需要仔细注册实现将要调用的接口的所有类。