使用 @Value
@Value
@Value
通常用于注入外部化属性:
- Java
- Kotlin
@Component
public class MovieRecommender {
private final String catalog;
public MovieRecommender(@Value("${catalog.name}") String catalog) {
this.catalog = catalog;
}
}
@Component
class MovieRecommender(@Value("\${catalog.name}") private val catalog: String)
使用以下配置:
- Java
- Kotlin
@Configuration
@PropertySource("classpath:application.properties")
public class AppConfig { }
@Configuration
@PropertySource("classpath:application.properties")
class AppConfig
以及以下的 application.properties
文件:
catalog.name=MovieCatalog
在这种情况下,catalog
参数和字段将等于 MovieCatalog
值。
Spring 提供了一个默认的宽松嵌入值解析器。它会尝试解析属性值,如果无法解析,属性名称(例如 ${catalog.name}
)将作为值注入。如果你想对不存在的值进行严格控制,你应该声明一个 PropertySourcesPlaceholderConfigurer
bean,如下例所示:
- Java
- Kotlin
@Configuration
public class AppConfig {
@Bean
public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
@Configuration
class AppConfig {
@Bean
fun propertyPlaceholderConfigurer() = PropertySourcesPlaceholderConfigurer()
}
在使用 JavaConfig 配置 PropertySourcesPlaceholderConfigurer
时,@Bean
方法必须是 static
。
使用上述配置可确保如果任何 ${}
占位符无法解析,则 Spring 初始化失败。也可以使用诸如 setPlaceholderPrefix
、setPlaceholderSuffix
、setValueSeparator
或 setEscapeCharacter
之类的方法来自定义占位符。
Spring Boot 默认配置了一个 PropertySourcesPlaceholderConfigurer
bean,该 bean 将从 application.properties
和 application.yml
文件中获取属性。
Spring 提供的内置转换器支持允许简单类型转换(例如转换为 Integer
或 int
)自动处理。多个逗号分隔的值可以自动转换为 String
数组,无需额外操作。
可以通过以下方式提供默认值:
- Java
- Kotlin
@Component
public class MovieRecommender {
private final String catalog;
public MovieRecommender(@Value("${catalog.name:defaultCatalog}") String catalog) {
this.catalog = catalog;
}
}
@Component
class MovieRecommender(@Value("\${catalog.name:defaultCatalog}") private val catalog: String)
Spring 的 BeanPostProcessor
在幕后使用 ConversionService
来处理将 @Value
中的 String
值转换为目标类型的过程。如果你想为自己的自定义类型提供转换支持,可以提供你自己的 ConversionService
bean 实例,如下例所示:
- Java
- Kotlin
@Configuration
public class AppConfig {
@Bean
public ConversionService conversionService() {
DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService();
conversionService.addConverter(new MyCustomConverter());
return conversionService;
}
}
@Configuration
class AppConfig {
@Bean
fun conversionService(): ConversionService {
return DefaultFormattingConversionService().apply {
addConverter(MyCustomConverter())
}
}
}
当 @Value
包含一个 SpEL 表达式 时,该值将在运行时动态计算,如以下示例所示:
- Java
- Kotlin
@Component
public class MovieRecommender {
private final String catalog;
public MovieRecommender(@Value("#{systemProperties['user.catalog'] + 'Catalog' }") String catalog) {
this.catalog = catalog;
}
}
@Component
class MovieRecommender(
@Value("#{systemProperties['user.catalog'] + 'Catalog' }") private val catalog: String)
SpEL 还支持使用更复杂的数据结构:
- Java
- Kotlin
@Component
public class MovieRecommender {
private final Map<String, Integer> countOfMoviesPerCatalog;
public MovieRecommender(
@Value("#{{'Thriller': 100, 'Comedy': 300}}") Map<String, Integer> countOfMoviesPerCatalog) {
this.countOfMoviesPerCatalog = countOfMoviesPerCatalog;
}
}
@Component
class MovieRecommender(
@Value("#{{'Thriller': 100, 'Comedy': 300}}") private val countOfMoviesPerCatalog: Map<String, Int>)