知識庫 / Spring RSS 訂閱

Spring @Value 快速指南

Spring
HongKong
9
02:35 PM · Dec 06 ,2025

1. 概述

在本快速教程中,我們將查看 Spring 註解 @Value

此註解可用於向 Spring 管理的 Bean 中的字段注入值,並且可應用於字段、構造函數或方法參數級別。

2. 設置應用程序

為了描述這種標註的不同使用方式,我們需要配置一個簡單的 Spring 應用程序配置類。

自然地,我們需要一個 屬性文件來定義我們想要使用 @Value 註解注入的值。因此,我們需要在配置類中定義一個 @PropertySource —— 與屬性文件名相關聯。

讓我們定義屬性文件:

value.from.file=Value got from the file
priority=high
listOfValues=A,B,C

3. 使用示例

作為一種基本且幾乎沒有用的示例,我們只能將“字符串值”從標註注入到字段中:

@Value("string value")
private String stringValue;

使用 @PropertySource 註解,允許我們使用帶有 @Value 註解的屬性文件中的值。

在下面的示例中,我們從文件中獲取 並將其分配給字段:

@Value("${value.from.file}")
private String valueFromFile;

我們還可以通過設置系統屬性來指定值,使用相同的語法。

假設我們已經定義了一個名為 systemValue 的系統屬性:

@Value("${systemValue}")
private String systemValue;

可以為可能未定義的屬性提供默認值。在此,值 some default 將被注入:

@Value("${unknown.param:some default}")
private String someDefault;

如果相同的屬性既作為系統屬性定義,又在屬性文件中定義,則系統屬性將被應用。

假設我們有一個屬性 priority 定義為系統屬性,值為 System property,同時在屬性文件中定義為其他值。則該值將為 System property

@Value("${priority}")
private String prioritySystemProperty;

有時,我們需要注入大量值。將它們定義為單個屬性的逗號分隔值,或者作為系統屬性並注入到數組中,將非常方便。

在第一部分中,我們定義了 listOfValues 屬性文件中的逗號分隔值,因此數組的值將是 ["A", "B", "C"]:

@Value("${listOfValues}")
private String[] valuesArray;

4. 藉助 SpEL 的高級示例

我們可以使用 SpEL 表達式獲取值。

如果系統屬性名為 priority,,則其值將被應用於字段:

@Value("#{systemProperties['priority']}")
private String spelValue;

如果未定義系統屬性,則將分配空值。

為了防止這種情況發生,我們可以為 SpEL 表達式提供默認值。如果未定義系統屬性,則可以獲取一些默認值用於該字段:

@Value("#{systemProperties['unknown'] ?: 'some default'}")
private String spelSomeDefault;

此外,我們還可以從其他 Bean 中使用字段值。假設我們有一個名為 someBean 的 Bean,其中包含一個名為 someValue 的字段,其值為 10。則 10 將被分配給該字段:

@Value("#{someBean.someValue}")
private Integer someBeanValue;

我們可以通過操作屬性來獲取一個包含值的 列表,這裏是一個包含字符串值 A、B 和 C 的列表:

@Value("#{'${listOfValues}'.split(',')}")
private List<String> valuesList;

5. 使用 @ValueMap

我們還可以使用 @Value 註解來注入 Map 屬性。

首先,我們需要在屬性文件中以 {key: ‘value’ } 的形式定義該屬性:

valuesMap={key1: '1', key2: '2', key3: '3'}

請注意,Map 中的值必須用單引號括起來。

現在我們可以將此值從屬性文件中注入為Map

@Value("#{${valuesMap}}")
private Map<String, Integer> valuesMap;

如果我們需要從 Map 中獲取特定鍵的值,我們只需要在表達式中添加鍵的名稱:

@Value("#{${valuesMap}.key1}")
private Integer valuesMapKey1;

如果對於 Map 中是否存在某個鍵不確定,我們應該選擇 一種更安全的表達方式,它不會拋出異常,而是當鍵不存在時將值設置為 null

@Value("#{${valuesMap}['unknownKey']}")
private Integer unknownMapKey;

我們還可以為可能不存在的屬性或鍵設置默認值

@Value("#{${unknownMap : {key1: '1', key2: '2'}}}")
private Map<String, Integer> unknownMap;

@Value("#{${valuesMap}['unknownKey'] ?: 5}")
private Integer unknownMapKeyWithDefaultValue;

Map 鍵值對也可以在注入之前進行過濾。

假設我們需要獲取僅包含值大於一個的鍵值對:

@Value("#{${valuesMap}.?[value>'1']}")
private Map<String, Integer> valuesMapFiltered;

我們還可以使用 @Value 註解來 注入所有當前系統屬性

@Value("#{systemProperties}")
private Map<String, String> systemPropertiesMap;

6. 使用 @Value 與構造函數注入

當我們使用 @Value 註解時,並不侷限於字段注入。 我們也可以將其與構造函數注入結合使用。

讓我們通過一個例子來演示:

@Component
@PropertySource("classpath:values.properties")
public class PriorityProvider {

    private String priority;

    @Autowired
    public PriorityProvider(@Value("${priority:normal}") String priority) {
        this.priority = priority;
    }

    // standard getter
}

在上述示例中,我們直接向我們的 PriorityProvider 的構造函數注入了 優先級

請注意,我們還提供了一個默認值,以防屬性未找到。

7. 使用 @Value 與 Setter 注入

類似於構造注入,我們也可以使用 @Value 與 setter 注入。

讓我們來看一個例子:

@Component
@PropertySource("classpath:values.properties")
public class CollectionProvider {

    private List<String> values = new ArrayList<>();

    @Autowired
    public void setValues(@Value("#{'${listOfValues}'.split(',')}") List<String> values) {
        this.values.addAll(values);
    }

    // standard getter
}

我們使用 SpEL 表達式將一個值列表注入到 setValues 方法中。

8. 使用 @Value 與記錄 (Records)

Java 14 引入了記錄 (Records) 以簡化不可變類的創建。 Spring 框架自 6.0.6 版本起支持 @Value 用於記錄注入:

@Component
@PropertySource("classpath:values.properties")
public record PriorityRecord(@Value("${priority:normal}") String priority) {}

在這裏,我們直接將值注入到記錄的構造函數中。

9. 結論

在本文中,我們探討了使用 @Value 註解與簡單文件屬性、系統屬性以及使用 SpEL 表達式計算的屬性的各種可能性。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.