요약
- Spring Boot 2.2 버전을 기점으로 ConfigurationProperties에 대한 사용성이 많이 변경됨
- Spring Boot 2.2버전 미만은 @Component + @ConfigurationProperties를 활용
- Spring Boot 2.2버전 이상은 @ConfigurationPropertiesScan + @ConfigurationProperties를 활용 (불변을 원한다면 @ConstructorBinding 추가)
아래 글은 Spring Boot 2.7.1에서 테스트한 내용을 기반으로 하고 있으며,
Spring Boot 2.2 버전 미만에서는 동작하지 않을 수 있습니다.
설명
- 외부 설정을 주입받을 때 사용
- 주로 application.properties, application.yml에 있는 설정파일을 주입받을 경우가 많음
- @ConfigurationPropertiesScan을 통해 @ConfigurationProperties 어노테이션이 붙어있는 클래스 or 함수에 값을 바인딩 해줌
//application.yml
van:
test: sunho
//Application.class
/**
* Application class에 @ConfigurationPropertiesScan을 선언해서 해당 클래스 하위의 모든 패키지들을 Scan
*/
@ConfigurationPropertiesScan
@SpringBootApplication
class Application
/**
* van으로 시작하는 property들을 바인딩
*/
@ConfigurationProperties(prefix = "van")
class VanConfig(
var test: String = "a"
)
- 다만 위와 같은 방식은 test가 가변이면서, notNull을 보장하기위한 default인자가 반드시 필요하다.
- ConfigurationProperties은 기본적으로 Setter로 값을 바인딩하기 때문
- 위와 같은 아쉬움을 해결하기 위해 @ConstructorBinding을 통해 생성자를 통한 바인딩을 할 수 있다.
/**
* ... 위와 동일
*/
/**
* van으로 시작하는 property들을 생성자를 통해 바인딩
*/
@ConstructorBinding
@ConfigurationProperties(prefix = "van")
class VanConfig(
var test: String = "a"
)
- Bean어노테이션과도 함께 사용 가능
//application.yml
van:
test: sunho
//Application.class
/**
* Application class에 @ConfigurationPropertiesScan을 선언해서 해당 클래스 하위의 모든 패키지들을 Scan
*/
@ConfigurationPropertiesScan
@SpringBootApplication
class Application
/**
* 일반 class 생성
*/
class VanProperties(
var test: String = "a",
val a: String,
val b: String
) {
companion object {
fun create(): VanProperties {
return VanProperties(a = "hello", b = "van", test = "에베베베베")
}
}
}
@Configuration
class VanConfiguration {
/**
* 객체 생성 후 (test에 에베베베베라는 값 할당)
* 값 바인딩 (application.yml 에 있는 van.test = sunho)
*/
@Bean
@ConfigurationProperties("van")
fun vanProperties(): VanProperties {
return VanProperties.create()
}
}
@Component
class Runner(
private val van: VanProperties
) : ApplicationRunner {
override fun run(args: ApplicationArguments?) {
println("a is ${van.a}")
println("b is ${van.b}")
/**
* 에베베베베가 아닌 sunho가 출력된다
*/
println("test is ${van.test}")
}
}
실제 사용
요구사항 1) Spring Boot의 DataSource를 HikariDataSource가 아닌 LazyConnectionDataSourceProxy로 변경
- LazyConnectionDataSourceProxy 사용하는 이유는 TBD
//application.yml
spring:
datasource:
hikari:
driver-class-name: org.h2.Driver
jdbc-url: jdbc:h2:mem://localhost/~/testdb;MODE=MYSQL
username: sa
password:
//DataBaseConfiguration.kt
@Configuration
class DataBaseConfiguration {
/**
* application.yml에 설정된 spring.datasource.hikari값들을 바인딩
*/
@Bean
@ConfigurationProperties("spring.datasource.hikari")
fun hikariConfig(): HikariConfig {
return HikariConfig()
}
/**
* hikariConfig를 기반으로 HikariDataSoure를 생성 후 LazyConnectionDataSourceProxy 생성
*/
@Bean
fun dataSource(hikariConfig: HikariConfig): DataSource {
val hikariDataSource = HikariDataSource(hikariConfig)
return LazyConnectionDataSourceProxy(hikariDataSource)
}
}
요구사항 2) google에 호출해야하는 api List들을 Properties로 관리
//application.yml
api:
google:
host: https://google.co.kr
headers:
Authorization: hello
Cookie: hh
customAuth: customAuth
endpoints:
users: /users
login: /login
logout: /logout
// GoogleApiProperties.kt
/**
* 불변으로 하기위해 @ConstructorBinding
*/
@ConstructorBinding
@ConfigurationProperties("api.google")
data class GoogleApiProperties(
private val host: String,
// headers는 key,value 매핑
private val headers: Map<String, String>,
private val endpoints: EndpointProperties
)
data class EndpointProperties(
private val users: String,
private val login: String,
private val logout: String
)
참고
'spring & spring boot' 카테고리의 다른 글
| [스터디] 스프링 부트 개념과 활용 - 3주차 ( ~ 3/5) (0) | 2022.03.04 |
|---|---|
| [스터디] 스프링 부트 개념과 활용 - 1주차 ( ~ 2/19) (0) | 2022.02.19 |
댓글