스프링부트 2.2부터 @ConstructorBinding을 이용해서 @ConfigurationProperties를 immutable하게 설계할 수 있습니다.

- @ConfigurationProperties이란 prefix에 매핑되는 외부 설정 값을 객체로 바인딩 시킬 수 있는 기능입니다.

   (자세한 건 문서를 참고하시면 좋을 거 같습니다)

 

 

기존 사용 방식

 

@Getter
@Setter
@ConfigurationProperties(prefix = "member")
public class MemberProperties {

  private String firstName;
  private String address;
  private int age;
}

 

application.yml

# application.yml

member:
  nick-name: brick
  address: seoul
  age: 10

 

Test

@SpringBootTest
class MemberPropertiesTest {

  @Autowired
  MemberProperties member;

  @DisplayName("memberProperties 외부 설정 주입")
  @Test
  void member_properties_test() {
    assertThat(member.getNickName()).isEqualTo("brick");
    assertThat(member.getAddress()).isEqualTo("seoul");
    assertThat(member.getAge()).isEqualTo(10);
  }
}

 

정상적으로 테스트가 통과했습니다.

 

 

하지만 위 코드에는 MemberProperties 값을 setter를 통해 바인딩을 하고 있으므로  객체의 값이 언제든 변경될 가능성이 있습니다.

이번엔 @ConstructorBinding을 이용해서 immutable하게 설계를 해보겠습니다.

 

After

@ConfigurationProperties("member")
@ConstructorBinding       // (1)
@Getter
public class MemberProperties {

  private final String nickName;
  private final String address;
  private final int age;
}

 

매우 간단합니다. Type 레벨에 @ConstructBinding을 붙이면 됩니다. 

 

@SpringBootApplication
@ConfigurationPropertiesScan // @EnableConfigurationProperties으로 일일이 등록하지 않아도 됨.
public class Application {

  public static void main(String[] args) {
    SpringApplication.run(TransactionApplication.class, args);
  }

}

 

유효성 검사도 가능합니다.

@ConfigurationProperties("member")
@ConstructorBinding
@Validated
@Getter
public class MemberProperties {

  private final String nickName;
  private final String address;
  @Min(1)
  private final int age;
}

 

테스트도 정상적으로 작동하는 걸 확인할 수 있습니다.

 

 

Reference

www.baeldung.com/configuration-properties-in-spring-boot