1. 概述
在 Spring Boot 应用中,一个常见的需求是将外部配置属性注入到 Spring Bean 中。通常我们会使用 @ConfigurationProperties
注解将一组配置绑定到一个类中。但如果我们只需要注入几个独立的配置项,也可以使用 @Value
注解来实现。
本文将介绍如何在 Kotlin 中使用 @Value
注解注入配置属性。
2. YAML 配置文件
我们首先在 src/main/resources
目录下创建一个名为 application-inject-value.yml
的 YAML 配置文件:
my-app:
magic-number: 42
magic-string: "It's a magic string"
magic-flag: true
magic-string-with-default: "It's another magic string"
⚠️ Spring 默认不支持从 YAML 文件加载配置到 @PropertySource
,所以我们需要自定义一个 YamlPropertySourceFactory
类来支持 YAML:
class YamlPropertySourceFactory : PropertySourceFactory {
override fun createPropertySource(@Nullable name: String?, encodedResource: EncodedResource): PropertySource<*> =
PropertiesPropertySource(encodedResource.resource.filename,
YamlPropertiesFactoryBean().also { it.setResources(encodedResource.resource) }.getObject()
)
}
然后,我们在 Spring Boot 主类上使用 @PropertySource
注解加载这个 YAML 文件:
@PropertySource(value = ["classpath:application-inject-value.yml"], factory = YamlPropertySourceFactory::class)
@SpringBootApplication(scanBasePackages = ["com.baeldung.theValueAnnotation"])
class KotlinValueInjectionApplication
接下来,我们就可以在组件中使用 @Value
注解注入这些配置了。
3. 使用 @Value 注入配置属性
在 Java 中,我们通常使用 @Value("${prop.name}")
的方式注入配置。但在 Kotlin 中,由于字符串模板也使用 $
符号,**我们需要对 $
进行转义,写成 \${
**。
我们创建一个 Spring 组件来演示注入:
@Component
class ValueBean(
@Value("\${my-app.magic-number}")
val magicNumber: Int,
@Value("\${my-app.magic-string}")
val magicString: String,
@Value("\${my-app.magic-flag}")
val magicFlag: Boolean,
)
✅ 这里我们使用了构造器注入方式注入配置属性,简洁又符合 Kotlin 风格。
为了验证注入是否成功,我们可以编写一个测试类:
@SpringBootTest
@TestConstructor(autowireMode = AutowireMode.ALL)
class TheValueAnnotationUnitTest(val valueBean: ValueBean) {
@Test
fun `test injected values`() {
with(valueBean) {
assertEquals(42, magicNumber)
assertEquals("It's a magic string", magicString)
assertTrue(magicFlag)
}
}
}
测试通过说明配置项已正确注入。
4. 使用默认值注入
有时候,我们希望为配置项提供一个默认值,以应对配置文件中可能缺失的情况。使用 @Value("${prop.name:default}")
格式即可实现。
我们扩展 ValueBean
类,添加两个带默认值的字段:
@Component
class ValueBean(
...
// 带默认值的字段
@Value("\${my-app.not-defined-value:1024}")
val magicNumberWithDefault: Int,
@Value("\${my-app.magic-string-with-default:default Value}")
val magicStringWithDefault: String,
)
配置中 my-app.not-defined-value
并不存在,所以会注入默认值 1024
;而 my-app.magic-string-with-default
已定义,所以会注入配置值。
测试代码如下:
with(valueBean) {
assertEquals(1024, magicNumberWithDefault)
assertEquals("It's another magic string", magicStringWithDefault)
}
5. 使用 null 作为默认值
除了非空默认值,我们有时也希望在配置缺失时使用 null
作为默认值。
在 Kotlin 中,**字段必须声明为可空类型(如 String?
)才能接受 null
**。我们继续扩展 ValueBean
:
@Component
class ValueBean(
...
// 使用 null 作为默认值
@Value("\${my-app.not-defined-value:null}")
val stringDefaultLiteralNull: String?,
@Value("\${my-app.not-defined-value:#{null}}")
val stringDefaultNull: String?
)
这两个字段虽然都试图注入不存在的配置项,但行为略有不同:
-
\${my-app.not-defined-value:null}
:注入字符串"null"
。 -
\${my-app.not-defined-value:#{null}}
:注入null
,因为#{null}
是 Spring 表达式(SpEL)中的null
字面量。
测试代码如下:
with(valueBean) {
assertEquals("null", stringDefaultLiteralNull)
assertNull(stringDefaultNull)
}
⚠️ 注意:"null"
是字符串,不是真正的 null
,容易踩坑!
6. 小结
本文介绍了如何在 Kotlin + Spring Boot 项目中使用 @Value
注解注入配置属性,包括:
✅ 使用 YAML 配置并加载到 Spring 上下文中
✅ Kotlin 中使用 @Value("\${...}")
注入配置
✅ 提供默认值:@Value("\${prop:default}")
✅ 使用 null
作为默认值:@Value("\${prop:#{null}}")
✅ 注意 Kotlin 的可空类型限制
完整代码可在 GitHub 上查看。