Serializable 구현 문제
- Serializable을 구현하면 생성자 이외의 방법으로 인스턴스 생성 가능
- 버그와 보안문제
-> 직렬화 프록시 패턴
SerializableProxy 구현
publicclassPeriodimplementsSerializable {
privatefinalDatestart;
privatefinalDateend;
publicPeriod(Datestart, Dateend) {
this.start = newDate(start.getTime());
this.end = newDate(end.getTime());
if(this.start.compareTo(this.end) > 0) {
thrownewIllegalArgumentException(start + "가 " + end + "보다 늦다.");
}
}
privatestaticclassSerializationProxyimplementsSerializable {
privatefinalDatestart;
privatefinalDateend;
publicSerializationProxy(Periodp) {
this.start = p.start;
this.end = p.end;
}
}
}직렬화 프록시는 바깥 클래스와 완전히 같은 필드로 구성
Period.writeReplace
publicclassPeriodimplementsSerializable {
privateObjectwriteReplace() {
returnnewSerializationProxy(this);
}
}직렬화시 호출
바깥 클래스(Period) 타입을 직렬화할 수 없음
Period.readObject
publicclassPeriodimplementsSerializable {
privatevoidreadObject(ObjectInputStreamstream) throwsInvalidObjectException {
thrownewInvalidObjectException("프록시가 필요합니다.");
}
}역직렬화시 호출
Period를 직접 역직렬화할 수 없음
Period.SerializableProxy.readResolve
publicclassPeriodimplementsSerializable {
privatestaticclassSerializationProxyimplementsSerializable {
privateObjectreadResolve() {
returnnewPeriod(start, end);
}
}
}직렬화 프록시를 통해서만 역직렬화 가능
생성자 혹은 정적 메서드를 통해서만 객체를 생성하므로 불변식이 깨질 위험이 낮음
Serializable 구현 문제
-> 직렬화 프록시 패턴
SerializableProxy 구현
직렬화 프록시는 바깥 클래스와 완전히 같은 필드로 구성
Period.writeReplace
직렬화시 호출
바깥 클래스(Period) 타입을 직렬화할 수 없음
Period.readObject
역직렬화시 호출
Period를 직접 역직렬화할 수 없음
Period.SerializableProxy.readResolve
직렬화 프록시를 통해서만 역직렬화 가능
생성자 혹은 정적 메서드를 통해서만 객체를 생성하므로 불변식이 깨질 위험이 낮음