【问题标题】:Serialization events in KryoKryo 中的序列化事件
【发布时间】:2012-09-07 21:03:26
【问题描述】:

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

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

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

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 Natan:register(A.class, new FieldSerializer(A.class, myhandler。这会序列化所有字段,包括子类,但是根本不会为子类调用自定义序列化程序。因此,我决定 Kryo 自定义仅适用于最终课程。 Nathan says that this conclusion is "invalid" and KryoSerializable solution "application-specific" and thinking otherwise "rude". 尽管有这样的解决方案,我还是决定发布我发现的通用方法。

【问题讨论】:

    标签: kryo


    【解决方案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;
        }
    
    }
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-18
      • 2016-07-02
      • 1970-01-01
      相关资源
      最近更新 更多