Spring Boot中如何从YAML注入复杂列表数据结构?
问题描述
我希望从如下YAML文件中注入对应的数据结构:
default: users: - id: 1 login: "user1" - id: 2 login: "user2"
我创建了对应的User类:
data class User ( val id: Integer, val login: String )
随后尝试了两种Spring Boot注入方式,但都导致应用启动失败:
方式一
@ConfigurationProperties(prefix = "default") data class UserProperties(val users: List<User>)
方式二(参考案例)
@Configuration class UserProperties { class Properties { val users: List<User>? = null } @get:ConfigurationProperties(prefix = "default") @get:Bean val properties: Properties get() = Properties() }
报错信息:
ReactiveWebServerApplicationContext Exception encountered during context initialization - cancelling refresh attempt: org.springframework.context.ApplicationContextException: Unable to start reactive web server
请问是否可以注入此类数据结构?正确的实现方式是什么?
解决方案
可以注入这类数据结构,问题出在类型匹配、配置绑定的细节上,以下是正确实现方式:
1. 修正User类的类型
Kotlin中优先使用原生Int而非包装类Integer,Spring Boot配置绑定对Kotlin原生类型支持更友好:
data class User( val id: Int, val login: String )
2. 正确配置@ConfigurationProperties绑定
方式一(推荐)
确保配置类被Spring识别,通过@EnableConfigurationProperties启用绑定,或者直接添加@Configuration注解:
// 方案1:单独配置类+启动类启用 @ConfigurationProperties(prefix = "default") data class UserProperties(val users: List<User>) @SpringBootApplication @EnableConfigurationProperties(UserProperties::class) class YourApplication fun main(args: Array<String>) { runApplication<YourApplication>(*args) } // 方案2:直接给配置类加@Configuration @Configuration @ConfigurationProperties(prefix = "default") data class UserProperties(val users: List<User>)
方式二(内部类实现优化)
Kotlin默认类是final的,Spring需要动态代理,所以内部类要加open修饰,同时用可变属性让Spring可以赋值:
@Configuration class UserPropertiesConfig { open class Properties { lateinit var users: List<User> // 用lateinit避免null,或用var users: List<User> = emptyList() } @Bean @ConfigurationProperties(prefix = "default") fun properties(): Properties { return Properties() } }
3. 排查报错核心原因
你看到的启动失败是表层异常,真正的配置绑定错误会嵌套在堆栈信息里,常见原因包括:
- 类型不匹配(比如用了
Integer而非Int) - 配置类未被Spring扫描到
- 不可变属性导致Spring无法赋值(比如方式二中的
val users: List<User>? = null)
验证注入结果
通过注入配置类验证数据是否绑定成功:
@RestController class TestController( private val userProperties: UserProperties ) { @GetMapping("/users") fun getUsers() = userProperties.users }
内容的提问来源于stack exchange,提问作者allen_d
相关产品推荐
相关产品推荐

