2012-09-07 5 views
1

어떻게 직렬화 이벤트를 수신합니까? 당신은 자바 직렬화에서Kryo의 직렬화 이벤트

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

을 정의 할 수 있으며, 객체 직렬화시이 메소드가 호출됩니다. Kryo에서 어떻게 같은 일을합니까? KryoSerializableExternalizable 모두 기본 직렬화 문제가 있습니다. 이벤트 처리기를 호출하면 기본 읽기/쓰기 개체가 필요합니다. 그러나 그런 것은 없습니다! ? 을 read(Kryo, Input)에서 호출하여 개체의 필드를 읽을 수 있지만 현재 개체를 채우는 대신 새 개체가 생성됩니다. 필드는 직렬화 만 A.class, I는 서브 클래스를 통해 serializationEvent() 이벤트를 받도록 언급,

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); 

그러나이 이유로, 나는 사용자 정의 시리얼을 소개했습니다. 따라서 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". 그런 결의에도 불구하고 나는 내가 발견 한 일반적인 방법을 발표하기로 결정했다.

답변

1

두 가지 해결책을 발견했습니다. newDefaultSerializer 오버라이드 (override) : 처음에는 무시 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); 
    } 

을 사용할 수 있습니다, 그것은 소스 코드의 가시성 변화를 필요로하고 나탄이 (기본값의 경우) 참조이 활성화 된 경우에만 작동하고 대신보다 안정적인 접근 방식을 권장 말한다 :

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; 
    } 

} 

효과적뿐만 아니라,이 방법은주의 깊게 호출하려고하는 인터페이스를 구현하는 모든 클래스를 등록 할 필요가 고생하지 않습니다.