Programing/OpenSource
[Lombok & Spring (Jackson)] @Getter(lazy=true)를 쓸 때 주의해야 할 점
나모찾기
2020. 11. 18. 18:33
효진님이 getter 에서 매번 객체를 만드는 것에 대해 이유를 물어봐서 한 번만 만들어지게 하기 위해서 아래와 같이 lazy 를 true로 했다.
import lombok.Getter;
public class TistoryIssueParams {
@Getter(lazy = true)
private final TistoryNumber tistoryNumber = TistoryNumber.of(tistoryNumberType, tistoryNumberValue);
이런 식으로 annotation을 달면 lombok은 AtomicReference 로 필드를 만들고 늦은 초기화를 하는 코드를 만든다.
늦은 초기화를 Double-checked locking idiom을 사용하는 것을 알 수 있다.
public class TistoryIssueParams {
private final AtomicReference<Object> tistoryNumber = new AtomicReference();
public TistoryNumber getTistoryNumber() {
Object value = this.tistoryNumber.get();
if (value == null) {
synchronized(this.tistoryNumber) {
value = this.tistoryNumber.get();
if (value == null) {
TistoryNumber actualValue = TistoryNumber.of(this.tistoryNumberType, this.tistoryNumberValue);
value = actualValue == null ? this.tistoryNumber : actualValue;
this.tistoryNumber.set(value);
}
}
}
return (TistoryNumber)((TistoryNumber)(value == this.tistoryNumber ? null : value));
}
문제는 Spring을 Controller의 파라미터로 받을 경우에 ClassCastException 예외가 발생할 수 있다.
이유는 Jackson이 AtomicReference<Object> 객체를 AtomicReference<TistoryNumber> 가 아닌 AtomicReference<LinkedHashMap> 로 인스턴스를 바꾸어 버리기 때문이다.
해결책
해결 방법은 간단하다.
Jackson에게 건들지마 하고 아래와 같이 @JsonIgnore 를 달아주면된다.
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter;
public class TistoryIssueParams {
@JsonIgnore
@Getter(lazy = true)
private final TistoryNumber tistoryNumber = TistoryNumber.of(tistoryNumberType, tistoryNumberValue);