使用 @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 初始化失敗。也可以使用 setPlaceholderPrefixsetPlaceholderSuffixsetValueSeparatorsetEscapeCharacter 等方法來自訂佔位符。

Spring Boot 預設組態 PropertySourcesPlaceholderConfigurer Bean,該 Bean 將從 application.propertiesapplication.yml 檔案取得屬性。

Spring 提供的內建轉換器支援允許自動處理簡單類型轉換 (例如轉換為 Integerint)。多個逗號分隔的值可以自動轉換為 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>)