@ConfigurationProperties
는 Spring Boot 에서 properties 파일에 정의된 프로퍼티 중 주어진 prefix 를 가지는 프로퍼티들을 POJO 에 매핑하여 Bean 으로 만들수 있게 해주는 어노테이션이다.
그럼 @ConfigurationProperties 의 다양한 쓰임새에 대해 알아보자.
단순한 형태의 Property @Configuration @ConfigurationProperties (prefix = "mail" )public class ConfigProperties { private String hostName; private int port; private String from; }
스프링이 Bean 을 application context 에 만들도록 @Configuration 을 꼭 같이 붙여줘야하며, 만약 붙이지 않았을 경우에는 main Spring application 클래스에 @EnableConfigurationProperties(ConfigProperties.class) 를 붙여줘야한다.
@SpringBootApplication @EnableConfigurationProperties (ConfigProperties.class ) public class DemoApplication { public static void main (String[] args) { SpringApplication.run(DemoApplication.class , args ) ; } }
스프링은 프로퍼티를 바인딩할 때 완화된 규칙을 적용하여 다음과같은 변형도 모두 같게 취급한다
mail.hostName mail.hostname mail.host_name mail.host-name mail.HOST_NAME
Spring Boot 2.2 스프링 부트 2.2 에서는 @ConfigurationProperties 클래스들을 모두 찾아서 등록해주므로 @Component, 혹은 @Configuration 과 같은 어노테이션이나 @EnableConfigurationProperties 를 붙일 필요가 없다.
중첩 Property 기본 자료형 뿐만 아니라 List, Map, Class 도 만들 수가 있다. 다음과 같은 클래스가 있을 때,
public class Credentials { private String authMethod; private String username; private String password; }
다음과 같은 ConfigProperties 클래스에 프로퍼티를 바인딩 하려면
public class ConfigProperties { private String host; private int port; private String from; private List<String> defaultRecipients; private Map<String, String> additionalHeaders; private Credentials credentials; }
다음과 같은 형태로 properties 를 작성하면 된다.
#Simple properties mail.hostname=mailer@mail.com mail.port=9000 mail.from=mailer@mail.com #List properties mail.defaultRecipients[0]=admin@mail.com mail.defaultRecipients[1]=owner@mail.com #Map Properties mail.additionalHeaders.redelivery=true mail.additionalHeaders.secure=true #Object properties mail.credentials.username=john mail.credentials.password=password mail.credentials.authMethod=SHA1
@Bean 메소드에 사용하기 POJO 뿐만 아니라 @Bean 어노테이션이 붙은 메소드에도 사용할 수 있다. 우리가 코드를 수정할 수 없는(어노테이션을 붙일 수 없는) 써드파티 컴포넌트에 바인딩할 때 유용하다. 예를 들어 다음과 같은 이미 컴파일된 클래스가 있을 때
public class Item { private String name; private int size; }
다음과 같이 @Bean 이 붙은 메소드에 @ConfigurationProperties 를 붙이면
@Configuration public class ConfigProperties { @Bean @ConfigurationProperties (prefix = "item" ) public Item item () { return new Item(); } }
메소드의 리턴 타입인 Item 객체에 바인딩된다.
Property 유효성 검사 아래와 같이 빈 문자열 검사, 문자열 길이 범위, 정수 범위, 정규표현식을 통한 문자열의 형태를 체크할 수 있다.
@NotBlank private String hostName;@Length (max = 4 , min = 1 )private String authMethod;@Min (1025 )@Max (65536 )private int port;@Pattern (regexp = "^[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,6}$" )private String from;
만약 유효성 검사가 실패하면 IllegalStateException 이 발생하여 main application 의 실행이 실패한다.
Property 변환 Duration, DataSize 와 같은 타입은 스프링이 자동으로 변환해준다.
Duration Duration 은 시간을 나타내는 타입이다. 다음과 같은 Configuration 클래스가 있다고 가정하자.
@ConfigurationProperties (prefix = "conversion" )public class PropertyConversion { private Duration timeInDefaultUnit; private Duration timeInNano; ... }
그럼, 다음과 같이 바인딩 할 수 있다.
conversion.sizeInDefaultUnit=300 conversion.sizeInGB=2GB conversion.sizeInTB=4
default 단위는 ms 이며, 만약 이를 바꾸려면 @DurationUnit 을 사용한다
DataSize DataSize 는 파일의 크기를 나타내는 타입이다. 다음과 같은 configuration 클래스가 있다고 가정하자.
private DataSize sizeInDefaultUnit; private DataSize sizeInGB; @DataSizeUnit (DataUnit.TERABYTES)private DataSize sizeInTB;
그럼 다윽뫄 같이 바인딩 할 수 있다.
conversion.sizeInDefaultUnit=300 conversion.sizeInGB=2GB conversion.sizeInTB=4
default 단위는 byte 이며, 이를 바꾸려면 @DataSizeUnit 을 사용한다
Custom Converter 커스텀 변환을 정의할 수도 있다. 다음과 같은 클래스에
public class Employee { private String name; private double salary; }
다음과 같이 바인딩 하려면
conversion.employee=john,2000
다음과 같은 커스텀 Converter 클래스를 정의하면 될것이다.
@Component @ConfigurationPropertiesBinding public class EmployeeConverter implements Converter <String , Employee > { @Override public Employee convert (String from) { String[] data = from.split("," ); return new Employee(data[0 ], Double.parseDouble(data[1 ])); } }
@ConstructorBinding 스프링 부트 2.2 부터 @ConstructorBinding 을 붙여서 configuration properties 를 바인딩할 수 있다. 이것은 곧 @ConfigurationProperties 이 붙은 클래스가 이제 Immutable 일 수 있다는 것을 의미한다.
@ConfigurationProperties (prefix = "mail.credentials" )@ConstructorBinding public class ImmutableCredentials { private final String authMethod; private final String username; private final String password; public ImmutableCredentials (String authMethod, String username, String password) { this .authMethod = authMethod; this .username = username; this .password = password; } public String getAuthMethod () { return authMethod; } public String getUsername () { return username; } public String getPassword () { return password; } }
생성자에는 우리가 비인딩 하고자 하는 프로퍼티를 모두 인자로 가져야 한다. 위의 ImmutableCredentials 클래스는 모든 필드가 final 이기때문에 setter 가 없다. 또한, 생성자로 프로퍼티를 바인딩 하기 위해서는 @EnableConfigurationProperties, 혹은 @ConfigurationPropertiesScan 를 사용하여 명시적으로 configuration 클래스 를 활성화 시켜줘야 한다.
참고: https://www.baeldung.com/configuration-properties-in-spring-boot