We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
제3자가 확장할 수 없는 클래스라면 가능한 직렬화 프록시 패턴을 사용하자. 이 패턴이 아마도 중요한 불변식을 안정적으로 직렬화해주는 가장 쉬운 방법일 것이다.
public final class Period implements Serializable { private final Date start; private final Date end; public Period(Date start, Date end) { this.start = new Date(start.getTime()); this.end = new Date(end.getTime()); // 생성자에 인수 검사 로직 있음 - 직렬화된 스트림을 조작해서 역직렬화하면 불변식 깨질 수도! if (this.start.compareTo(this.end) > 0) throw new IllegalArgumentException( start + " after " + end); } public Date start () { return new Date(start.getTime()); } public Date end () { return new Date(end.getTime()); } public String toString() { return start + " - " + end; } // 프록시 클래스 private static class SerializationProxy implements Serializable { // 바깥 클래스를 논리적으로 표현 private final Date start; private final Date end; // 생성자 : 바깥 클래스를 받아 데이터 복사 SerializationProxy(Period p) { this.start = p.start; this.end = p.end; } // 프록시로 역직렬화하면 바깥 클래스의 생성자를 호출, 불변식 지킬 수 있음 private Object readResolve() { return new Period(start, end); } private static final long serialVersionUID = 234098243823485285L; // Any number will do (Item 87) } // 직렬화가 이뤄지기 전에 바깥 클래스의 인스턴스를 직렬화 프록시로 변환함 // 덕분에 직렬화 시스템은 바깥 클래스의 직렬화된 인스턴스를 생성할 수 없고 오직 프록시로만 접근 가능 private Object writeReplace() { return new SerializationProxy(this); } // 공격자가 불변식을 훼손하고자 readObject를 호출할때 예외를 던져 방어 private void readObject(ObjectInputStream stream) throws InvalidObjectException { throw new InvalidObjectException("Proxy required"); } }
프록시 패턴을 사용하는 예시 : EnumSet
private static class SerializationProxy<E extends Enum<E>> implements java.io.Serializable { private static final Enum<?>[] ZERO_LENGTH_ENUM_ARRAY = new Enum<?>[0]; private final Class<E> elementType; private final Enum<?>[] elements; SerializationProxy(EnumSet<E> set) { elementType = set.elementType; elements = set.toArray(ZERO_LENGTH_ENUM_ARRAY); } @SuppressWarnings("unchecked") @java.io.Serial private Object readResolve() { EnumSet<E> result = EnumSet.noneOf(elementType); // 정적 팩터리 메소드 사용하여 인스턴스 생성 for (Enum<?> e : elements) result.add((E)e); return result; } @java.io.Serial private static final long serialVersionUID = 362491234563181265L; }
The text was updated successfully, but these errors were encountered:
No branches or pull requests
직렬화 프록시 패턴
구현
방어적 복사 vs 프록시
프록시 패턴을 사용하는 예시 : EnumSet
직렬화 프록시 패턴의 한계
The text was updated successfully, but these errors were encountered: