Using @Value

@Value 通常用于注入外部化属性:

@Value is typically used to inject externalized properties:

  • 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)

使用以下配置:

With the following configuration:

  • Java

  • Kotlin

@Configuration
@PropertySource("classpath:application.properties")
public class AppConfig { }
@Configuration
@PropertySource("classpath:application.properties")
class AppConfig

和以下 application.properties 文件:

And the following application.properties file:

catalog.name=MovieCatalog

在这种情况下,catalog 参数和字段将等于 MovieCatalog 值。

In that case, the catalog parameter and field will be equal to the MovieCatalog value.

Spring 提供了默认的宽松嵌入式值解析器。它将尝试解析属性值,如果无法解析,将注入属性名称(例如 ${catalog.name})作为值。如果您想要对不存在的值进行严格控制,则应声明一个 PropertySourcesPlaceholderConfigurer bean,如下例所示:

A default lenient embedded value resolver is provided by Spring. It will try to resolve the property value and if it cannot be resolved, the property name (for example ${catalog.name}) will be injected as the value. If you want to maintain strict control over nonexistent values, you should declare a PropertySourcesPlaceholderConfigurer bean, as the following example shows:

  • 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

When configuring a PropertySourcesPlaceholderConfigurer using JavaConfig, the @Bean method must be static.

使用上述配置可确保在无法解析任何 ${} 占位符时,Spring 初始化失败。还可以使用诸如 setPlaceholderPrefixsetPlaceholderSuffixsetValueSeparatorsetEscapeCharacter 的方法来自定义占位符。

Using the above configuration ensures Spring initialization failure if any ${} placeholder could not be resolved. It is also possible to use methods like setPlaceholderPrefix, setPlaceholderSuffix, setValueSeparator, or setEscapeCharacter to customize placeholders.

Spring Boot 默认配置一个 PropertySourcesPlaceholderConfigurer bean,该 bean 将从 application.propertiesapplication.yml 文件中获取属性。

Spring Boot configures by default a PropertySourcesPlaceholderConfigurer bean that will get properties from application.properties and application.yml files.

Spring 提供的内置转换器支持允许自动处理简单类型转换(例如,转换为 Integerint)。可以自动将多个逗号分隔值转换为 String 数组,而无需其他操作。

Built-in converter support provided by Spring allows simple type conversion (to Integer or int for example) to be automatically handled. Multiple comma-separated values can be automatically converted to String array without extra effort.

可以提供默认值,如下所示:

It is possible to provide a default value as following:

  • 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 实例,如下例所示:

A Spring BeanPostProcessor uses a ConversionService behind the scenes to handle the process for converting the String value in @Value to the target type. If you want to provide conversion support for your own custom type, you can provide your own ConversionService bean instance as the following example shows:

  • 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`表达式 时,如下面的示例所示,该值会在运行时被动态计算:

When @Value contains a SpEL expression the value will be dynamically computed at runtime as the following example shows:

  • 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 还支持使用更复杂的数据结构:

SpEL also enables the use of more complex data structures:

  • 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>)