스프링부트 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