https://www.baeldung.com/configuration-properties-in-spring-boot/ 를 번역함.
1. 소개
Spring Boot에는 외부화된 구성과 속성 파일에 정의된 속성에 대한 쉬운 액세스를 포함하여 많은 유용한 기능이 있습니다 . 이전 자습서 에서는 이를 수행할 수 있는 다양한 방법을 설명했습니다.
이제 @ConfigurationProperties 주석을 더 자세히 살펴보겠습니다.
2. 설정
이 튜토리얼은 상당히 표준적인 설정을 사용합니다. pom.xml에 spring-boot-starter-parent 를 부모 로 추가하는 것으로 시작합니다 .
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.0</version>
<relativePath/>
</parent>
파일에 정의된 속성을 검증할 수 있으려면 JSR-303의 구현도 필요하며 hibernate-validator 가 그 중 하나입니다.
pom.xml 에도 추가해 보겠습니다 .
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.16.Final</version>
</dependency>
"최대 절전 모드 검사기 시작" 페이지에 자세한 내용이 있습니다.
3. 단순 속성
공식 문서에서는 구성 속성을 별도의 POJO로 분리할 것을 권장 합니다.
다음을 수행하여 시작하겠습니다.
@Configuration
@ConfigurationProperties(prefix = "mail")
public class ConfigProperties {
private String hostName;
private int port;
private String from;
// standard getters and setters
}
Spring이 애플리케이션 컨텍스트에서 Spring 빈을 생성 하도록 @Configuration을 사용 합니다.
@ConfigurationProperties 는 모두 동일한 접두사를 갖는 계층적 속성에서 가장 잘 작동합니다. 따라서 mail 접두사를 추가합니다.
Spring 프레임워크는 표준 Java bean setter를 사용하므로 각 속성에 대한 setter를 선언해야 합니다.
참고: POJO에서 @Configuration 을 사용하지 않으면 기본 Spring 애플리케이션 클래스에 @EnableConfigurationProperties(ConfigProperties.class) 를 추가 하여 속성을 POJO에 바인딩해야 합니다.
@SpringBootApplication
@EnableConfigurationProperties(ConfigProperties.class)
public class EnableConfigurationDemoApplication {
public static void main(String[] args) {
SpringApplication.run(EnableConfigurationDemoApplication.class, args);
}
}
그게 다야! Spring은 ConfigProperties 클래스 의 필드 중 하나와 이름이 같고 mail 접두사가 있는 속성 파일에 정의된 모든 속성을 자동으로 바인딩합니다 .
Spring은 속성을 바인딩하기 위해 몇 가지 완화된 규칙을 사용합니다. 결과적으로 다음 변형은 모두 hostName 속성에 바인딩됩니다 .
mail.hostName
mail.hostname
mail.host_name
mail.host-name
mail.HOST_NAME
따라서 다음 속성 파일을 사용하여 모든 필드를 설정할 수 있습니다.
#Simple properties
[email protected]
mail.port=9000
[email protected]
3.1. 스프링 부트 2.2
현재 봄 부팅 2.2 , 봄이 찾아 레지스터 @ConfigurationProperties 클래스 경로 검사를 통해 클래스를 . 따라서 @Component (및 @Configuration과 같은 기타 메타 주석)로 이러한 클래스에 주석을 달거나 @EnableConfigurationProperties를 사용할 필요가 없습니다.
@ConfigurationProperties(prefix = "mail")
public class ConfigProperties {
private String hostName;
private int port;
private String from;
// standard getters and setters
}
@SpringBootApplication에 의해 활성화된 클래스 경로 스캐너 는 @Component로 이 클래스에 주석을 달지 않았음에도 불구 하고 ConfigProperties 클래스를 찾습니다 .
또한 @ConfigurationPropertiesScan 주석을 사용 하여 구성 속성 클래스의 사용자 지정 위치를 스캔 할 수 있습니다 .
@SpringBootApplication
@ConfigurationPropertiesScan("com.baeldung.configurationproperties")
public class EnableConfigurationDemoApplication {
public static void main(String[] args) {
SpringApplication.run(EnableConfigurationDemoApplication.class, args);
}
}
이런 식으로 Spring은 com.baeldung.properties 패키지 에서만 구성 속성 클래스를 찾습니다 .
4. 중첩 속성
목록, 맵 및 클래스 에 중첩된 속성을 가질 수 있습니다 .
일부 중첩 속성에 사용할 새 Credentials 클래스를 만들어 보겠습니다 .
public class Credentials {
private String authMethod;
private String username;
private String password;
// standard getters and setters
}
우리는 또한 업데이트해야 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;
// standard getters and setters
}
다음 속성 파일은 모든 필드를 설정합니다.
#Simple properties
[email protected]
mail.port=9000
[email protected]
#List properties
mail.defaultRecipients[0][email protected]
mail.defaultRecipients[1][email protected]
#Map Properties
mail.additionalHeaders.redelivery=true
mail.additionalHeaders.secure=true
#Object properties
mail.credentials.username=john
mail.credentials.password=password
mail.credentials.authMethod=SHA1
5. @Bean 메소드 에서 @ConfigurationProperties 사용하기
@Bean 주석이 달린 메소드 에서 @ConfigurationProperties 주석을 사용할 수도 있습니다 .
이 접근 방식은 우리가 제어할 수 없는 타사 구성 요소에 속성을 바인딩하려는 경우에 특히 유용할 수 있습니다.
다음 예제에서 사용할 간단한 Item 클래스를 만들어 보겠습니다 .
public class Item {
private String name;
private int size;
// standard getters and setters
}
이제 @Bean 메서드에서 @ConfigurationProperties 를 사용 하여 외부화된 속성을 Item 인스턴스 에 바인딩 하는 방법을 살펴보겠습니다 .
@Configuration
public class ConfigProperties {
@Bean
@ConfigurationProperties(prefix = "item")
public Item item() {
return new Item();
}
}
결과적으로 항목 접두사가 붙은 속성은 Spring 컨텍스트에서 관리 하는 항목 인스턴스에 매핑됩니다 .
6. 속성 검증
@ConfigurationProperties 는 JSR-303 형식을 사용하여 속성의 유효성 검사를 제공합니다. 이것은 모든 종류의 깔끔한 것을 허용합니다.
예를 들어 hostName 속성을 필수로 지정해 보겠습니다 .
@NotBlank
private String hostName;
다음으로 authMethod 속성을 1~4자 길이로 만들어 보겠습니다 .
@Length(max = 4, min = 1)
private String authMethod;
그런 다음 1025에서 65536까지 의 포트 속성:
@Min(1025)
@Max(65536)
private int port;
마지막으로 from 속성은 이메일 주소 형식과 일치해야 합니다.
@Pattern(regexp = "^[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,6}$")
private String from;
이는 코드에서 if – else 조건을 많이 줄이는 데 도움이 되며 훨씬 깨끗하고 간결해 보입니다.
이러한 유효성 검사 중 하나라도 실패하면 기본 응용 프로그램이 IllegalStateException 으로 시작하는 데 실패 합니다 .
Hibernate Validation 프레임워크는 표준 Java Bean getter 및 setter를 사용하므로 각 속성에 대해 getter 및 setter를 선언하는 것이 중요합니다.
7. 재산 전환
@ConfigurationProperties 는 속성을 해당 빈에 바인딩하는 여러 유형의 변환을 지원합니다.
7.1. 지속
속성을 Duration 객체 로 변환하는 것부터 살펴보겠습니다 .
여기에 Duration 유형의 두 필드가 있습니다 .
@ConfigurationProperties(prefix = "conversion")
public class PropertyConversion {
private Duration timeInDefaultUnit;
private Duration timeInNano;
...
}
이것은 우리의 속성 파일입니다:
conversion.timeInDefaultUnit=10
conversion.timeInNano=9ns
결과적으로 timeInDefaultUnit 필드 의 값은 10밀리초이고 timeInNano 의 값은 9나노초입니다.
지원되는 단위는 각각 나노초, 마이크로초, 밀리초, 초, 분, 시간 및 일의 경우 ns, us, ms, s, m, h 및 d 입니다.
기본 단위는 밀리초입니다. 즉, 숫자 값 옆에 단위를 지정하지 않으면 Spring이 값을 밀리초로 변환합니다.
@DurationUnit을 사용하여 기본 단위를 재정의할 수도 있습니다 .
@DurationUnit(ChronoUnit.DAYS)
private Duration timeInDays;
해당 속성은 다음과 같습니다.
conversion.timeInDays=2
7.2. 데이터 크기
마찬가지로 Spring Boot @ConfigurationProperties 는 DataSize 유형 변환을 지원합니다 .
DataSize 유형의 세 필드를 추가해 보겠습니다 .
private DataSize sizeInDefaultUnit;
private DataSize sizeInGB;
@DataSizeUnit(DataUnit.TERABYTES)
private DataSize sizeInTB;
해당 속성은 다음과 같습니다.
conversion.sizeInDefaultUnit=300
conversion.sizeInGB=2GB
conversion.sizeInTB=4
이 경우 기본 단위가 바이트 이므로 sizeInDefaultUnit 값은 300바이트가 됩니다.
지원되는 단위는 B, KB, MB, GB 및 TB입니다. @DataSizeUnit을 사용하여 기본 단위를 재정의할 수도 있습니다 .
7.3. 사용자 정의 변환기
속성을 특정 클래스 유형으로 변환하는 것을 지원하기 위해 자체 사용자 정의 변환기 를 추가할 수도 있습니다 .
간단한 Employee 클래스를 추가해 보겠습니다 .
public class Employee {
private String name;
private double salary;
}
그런 다음 이 속성을 변환하는 사용자 지정 변환기를 만듭니다.
conversion.employee=john,2000
Employee 유형의 파일로 변환합니다 .
private Employee employee;
Converter 인터페이스 를 구현 한 다음 @ConfigurationPropertiesBinding 주석을 사용 하여 사용자 지정 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]));
}
}
8. 불변 @ConfigurationProperties 바인딩
Spring Boot 2.2부터 @ConstructorBinding 주석을 사용하여 구성 속성을 바인딩할 수 있습니다 .
이것은 본질적으로 @ConfigurationProperties 주석이 달린 클래스가 이제 변경 불가능할 수 있음을 의미합니다 .
@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;
}
}
보시다시피 @ConstructorBinding을 사용할 때 바인딩하려는 모든 매개변수를 생성자에 제공해야 합니다.
ImmutableCredentials의 모든 필드 는 최종적입니다. 또한 setter 메서드가 없습니다.
또한 생성자 바인딩을 사용하려면 @EnableConfigurationProperties 또는 @ConfigurationPropertiesScan 을 사용하여 구성 클래스를 명시적으로 활성화해야 한다는 점을 강조하는 것이 중요합니다 .
9. 자바 (16) 기록 들
Java 16 은 JEP 395의 일부로 레코드 유형을 도입했습니다 . 레코드는 변경할 수 없는 데이터의 투명한 전달자 역할을 하는 클래스입니다. 따라서 구성 보유자 및 DTO에 대한 완벽한 후보입니다. 사실 Spring Boot에서 Java 레코드를 구성 속성으로 정의할 수 있습니다 . 예를 들어 이전 예제는 다음과 같이 다시 작성할 수 있습니다.
@ConstructorBinding
@ConfigurationProperties(prefix = "mail.credentials")
public record ImmutableCredentials(String authMethod, String username, String password) {
}
분명히 모든 시끄러운 getter 및 setter에 비해 더 간결합니다.
또한 Spring Boot 2.6 부터 단일 생성자 레코드의 경우 @ConstructorBinding 주석을 삭제할 수 있습니다 . 그러나 레코드에 여러 생성자가 있는 경우 @ConstructorBinding 을 사용하여 속성 바인딩에 사용할 생성자를 식별해야 합니다.
10. 결론
이 기사에서는 @ConfigurationProperties 주석 을 살펴보고 완화된 바인딩 및 Bean 유효성 검사와 같이 주석이 제공하는 몇 가지 유용한 기능을 강조했습니다.
평소와 같이 코드는 Github에서 사용할 수 있습니다 .