GeezerVisonThe World Wide Web, restored to 800 pixels of glory. |
| Home|About|Gaming cabinet|Archives|How it works|Starter sites |
GeezerVison is showing github.com — 아이템 90. 직렬화된 인스턴스 대신 직렬화 프록시 사용을 검토하라 · Issue #206 · Study-2-Effective-Java/Effective-Java Open Labels 12장 직렬화이펙티브 자바 12장 (직렬화)이펙티브 자바 12장 (직렬화) DescriptionDiscussed in https://github.com/orgs/Study-2-Effective-Java/discussions/203Originally posted by JoisFe April 9, 2023 아이템 90. 직렬화된 인스턴스 대신 직렬화 프록시 사용을 검토하라문제점
버그와 보안 문제가 일어날 가능성이 커짐해결책직렬화 프록시 패턴 (serialization proxy pattern)
public final class Period { private final Date start; private final Date end; Period(Date start, Date end) { if (start.compareTo(end) > 0) { throw new IllegalArgumentException(start + "가 " + end + "보다 늦다."); } this.start = start; this.end = end; } public Date start() { return this.start; } public Date end() { return this.end; } private static class SerializationProxy implements Serializable { private final Date start; private final Date end; public SerializationProxy(Period p) { this.start = p.start; this.end = p.end; } // Period.SerializationProxy 용 readResolve 메서드 private Object readResolve() { return new Period(this.start, this.end); } } private static final long serialVersionUID = 453452354; private static final long serialVersionUID = 453452354; // 직렬화 프록시 패턴용 writeReplace 메서드 private Object writeReplace() { return new SerializationProxy(this); } // 직렬화 프록시 패턴용 readObject 메서드 private Object readObject(ObjectInputStream stream) throws InvalidObjectException { throw new InvalidObjectException("프록시가 필요합니다."); } }
// 직렬화 프록시 패턴용 writeReplace 메서드 private Object writeReplace() { return new SerializationProxy(this); }
// 직렬화 프록시 패턴용 readObject 메서드 private Object readObject(ObjectInputStream stream) throws InvalidObjectException { throw new InvalidObjectException("프록시가 필요합니다."); }
// Period.SerializationProxy 용 readResolve 메서드 private Object readResolve() { return new Period(this.start, this.end); }
프록시 패턴 vs 방어적 복사
직렬화 프록시 패턴이 readObject 에서의 방어적 복사보다 강력한 경우
EX) EnumSet (#91)
EnumSet 직렬화 프록시 패턴
private static class SerializationProxy <E extends Enum<E>> implements Serializable { // 이 EnumSet의 원소 타입 private final Class<E> elementType; // 이 EnumSet 안의 원소들 private final Enum<?>[] elements; SerializationProxy(Enum<E> set) { this.elementType = set.elementType; this.elements = set.toArray(new Enum<?>[0]); } private Object readResolve() { EnumSet<E> result = EnumSet.noneOf(this.elementType); for (Enum<?> e : this.elements) { result.add((E) e); } return result; } private static final long serialVersionUID = 23542435L; } 직렬화 프록시 패턴의 한계1. 클라이언트가 멋대로 확장할 수 있는 클래스에는 적용할 수 없음2. 객체 그래프에 순환이 있는 클래스에도 적용할 수 없음
직렬화 프록시 패턴이 주는 대가직렬화 프록시 패턴은 강력함과 안정성을 주지만 그만한 대가가 따름
정리제 3자가 확장할 수 없는 클래스라면 가능한 한 직렬화 프록시 패턴을 사용하자!
ActivityMetadataMetadataAssigneesLabels12장 직렬화이펙티브 자바 12장 (직렬화)이펙티브 자바 12장 (직렬화) TypeProjectsMilestoneRelationshipsDevelopmentIssue actions |
| You are visitor 01402503 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |