(Spring) annotation - lombok, builder
@Data
https://projectlombok.org/features/Data
- @Data = RequiredArgsConstructor + ToString + EqualsAndHashCode + Getter + Setter- lombok.noArgsConstructor.extraPrivate=true이면 private NoArgsConstructor 까지 붙는다. (1.16.22에서는 기본으로 활성화) 단, 필드 final 아닐 때
 
- 여기서 RequiredArgsConstructor는 다른 Constructor 애너테이션이나 명시적으로 선언된 Constructor가 없을 때만 붙는다.
- callSuper를 설정해야 하는 경우 해당 애너테이션과 Data를 함께 써도 된다. (설정된 애너테이션을 defer 처리 해주기 때문에 순서 상관 없다.)
이름과 파라미터 수
가 같은 메서드가 사용자 정의 Setter가 있다면 @Setter를 붙여도 기본 타입 세터가 만들어지지 않는다.
1
2
3
4
5
6
// @Setter 소용 없다.
private int code
public void setCode(ResponseCode code) { } // 이게 있으면, @Setter를 붙여도 아래 함수가 자동으로 생성되지 않기 때문에
public void setCode(int code) { }    // 이렇게 직접 적어주어야만 한다.
@ConstructorProperties
lombok 1.16.20 부터 롬복 애너테이션 사용해서 생성된 생성자에 @ConstructorProperties를 기본으로 붙여주지 않는다.
- https://projectlombok.org/features/constructor
- 관련 옵션 lombok.anyConstructor.addConstructorProperties 참고
@Builder
- 빌더를 직접 정의한다면…
item2/builder/NutritionFacts.java
- 빌더를 왜 쓸까? [Effective Java] 2장 객체 생성과 파괴
@Builder를 붙이면?
- @AllArgsConstructor(access = AccessLevel.PACKAGE)로 생성자가 만들어진다.
- @Data를 붙였을 때 따라오는 @RequiredArgsConstructor가 무시된다.
- 그러나 명시적으로 @RequiredArgsConstructor, @NoArgsConstructor, @AllArgsConstructor를 붙여주는 경우 public 생성자로도 접근이 가능하다.- @NoArgsConstructor나 @RequiredArgsConstructor는 단독으로 @Builder와 함께 사용하는 경우 AllArgsConstructor가 없다고 에러가 발생하므로 @AllArgsConstructor도 같이 붙여주어야 한다.
 
- 그래서… @Builder + @Data 조합으로 사용하거나 (이러면 @Setter 생성되어 final이 아니면 나쁘다.)1 2 3 4 5 6 // @NoArgs가 꼭 필요한 경우 (MyBatis) NoArgs 때문에 final을 못쓰기 때문에 Setter가 없어야 한다. @Builder @Getter @ToString @NoArgsConstructor @AllArgsConstructor 
- 근데 이런 케이스는 거의 없기도 하고, 빌더와 다른 생성자를 함께 두는게 좀 어색하기도 하다.
- MyBatis에서 (useActualParamName 옵션 없는 경우 && custom 생성자를 사용하는 경우) 생성자 파라미터 정의 순서대로 매핑이 되는 것을 방지하기 위해 NoArgs를 넣어주는 경우도 있는데, 근본적으로 useActualParamName을 활성화 해주는게 올바른 접근이다.
- [Spring] DB 관련 : Mybatis
- 빌더와 상속 :https://www.baeldung.com/lombok-builder-inheritance
빌더를 사용하면서, 몇몇 필수값은 반드시 입력 받고 싶다면?
- 아무 설정도 안하면, Class.builder().build()해도 만들어지기 때문에 필수값을 강제로 받으려면 다른 방법이 필요하다.
- required argument를 지정하고 싶다면 builderMethodName을 사용한다.
- https://stackoverflow.com/questions/29885428/required-arguments-with-a-lombok-builder
- https://deepweller.tistory.com/18
- builderMethodName에서 기본값으로 초기화하고, 외부에서 .field()로 다시 초기화하면 덮어 써지므로 필요한 경우 활용 가능.
빌더를 사용하면서, 필드를 기본값으로 초기화 하고 싶다면!?
- 필드에 =으로 기본값으로 초기화하려면, 대상 필드에@Builder.Default를 사용해야 하는데…- 이 방식은@Builder.Default는 쓰지 않는 것이 좋다 라는 얘기도 있고,
- f1 = f2.getName()요런 식으로 다른 필드의 속성을 이용해서 또 다른 필드를 초기화하는건 불가능하다. (빌더가 static이라, static context에서 non-static 필드를 참조할 수가 없당)
- 외부에서 빌더를 통해 객체 생성 시 해당 필드를 .field()로 초기화 할 수 있기 때문에, 해당 필드 초기화 권한을 내부로 한정하는 것도 불가능하다. (필드가 final이 아닌 경우)
 
- 생성자에 @Builder 붙이면 된다.- 내부적으로만 초기화 할 값들은 생성자 파라미터에서 빼버리면 되고
- 옵셔널 값의 경우 생성자 파라미터에 두고 null check해서 할당하면 된다.
 
특정 필드는 외부에서 받지 않고 내부에서 자체 초기화 하고 싶다면?
생성자에 @Builder 쓰면 생성자 파라미터에 있는 것만 빌더로 받아서 생성자로 넘어온다. 생성자에서 자체 초기화해주면 된다.
Kotlin의 data는 copy()를 지원해주어 객체를 불변으로 다루기 편한데… lombok에는 이런 기능이 없나?
You can use @Builder for copy constructors: foo.toBuilder().build() makes a shallow clone. Consider suppressing the generating of the builder method if you just want this functionality, by using: @Builder(toBuilder = true, builderMethodName = “”).
https://projectlombok.org/features/Builder
https://github.com/projectlombok/lombok/issues/908
Lombok 설치
- IntelliJ에서 - Preferences -> Build, Execution, Deployment -> Compiler, Annotation Processors. Click Enable Annotation Processing반드시 해준다. 이걸 안하면 cannot fine symbol 에러 또는 무슨 길이가 다르다느니 하는 빌드 에러가 발생함.
- (생략가능)IntelliJ Perference에서 lombok 플러그인 검색해서 설치한다. 이걸 설치 안하면 컴파일은 가능하지만, lombok에서 만들어준 getter,setter,constructor 등에 접근하려 할 때 IDE가 이를 resolve하지 못해 빨간색으로 뜬다. 다시 말하지만 컴파일은 가능함. 
3.여기서 The Lombok Gradle Plugin 부분을 따라하면 된다. 2번을 생략했다면 Gradle without a plugin 부분을 따라하면 된다. 그리고 뭔가 수정했다면 꼭 그냥 빌드가 아니라 Rebuild를 해보기 바란다.
#####