Spring @Value

1. 概述

Spring 的*@Value*注释提供了一种将属性值注入组件的便捷方法。在属性可能不存在的情况下提供合理的默认值也非常有用。

这就是我们将在本文中关注的内容——如何为*@Value* Spring 注释指定默认值。有关*@Value*的更详细的快速指南,请参阅此处的文章。

2. 字符串默认值

让我们看一下为String属性设置默认值的基本语法:

@Value("${some.key:my default value}")
private String stringWithDefaultValue;

如果some.key无法解析,则stringW ithDefaultValue将设置为“我的默认值”的默认值

同样,我们可以设置一个零长度的字符串作为默认值:

@Value("${some.key:})"
private String stringWithBlankDefaultValue;

3. 原语

要为基本类型(例如boolean和*int )*设置默认值,我们使用文字值:

@Value("${some.key:true}")
private boolean booleanWithDefaultValue;
@Value("${some.key:42}")
private int intWithDefaultValue;

如果我们愿意,我们可以通过将类型更改为BooleanInteger来使用原始包装器。

4. 数组

我们还可以将逗号分隔的值列表注入数组:

@Value("${some.key:one,two,three}")
private String[] stringArrayWithDefaults;

@Value("${some.key:1,2,3}")
private int[] intArrayWithDefaults;

在上面的第一个示例中,值“ one”、“ *two”*和“ three”作为默认值注入到stringArrayWithDefaults 中

在第二个示例中,值1、2 和 3作为默认值注入intArrayWithDefaults 中

5. 使用 SpEL

我们还可以使用 Spring 表达式语言 (SpEL) 来指定表达式和默认值。

在下面的示例中,我们希望将some.system.key设置为系统属性,如果没有设置,我们希望使用“*我的默认系统属性值”*作为默认值:

@Value("#{systemProperties['some.key'] ?: 'my default system property value'}")
private String spelWithDefaultValue;

六,结论

在这篇快速文章中,我们研究了如何为我们希望使用 Spring 的*@Value*注释注入的属性设置默认值。

像往常一样,本文中使用的所有代码示例都可以在GitHub 项目中找到。

Spring @Value 快速指南

1. 概述

在这个快速教程中,我们将看看*@Value* Spring 注释。

此注解可用于将值注入 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("${value.from.file}")
private String valueFromFile;

我们还可以使用相同的语法从系统属性设置值。

假设我们已经定义了一个名为systemValue的系统属性:

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

可以为可能未定义的属性提供默认值。在这里, 将注入一些默认值:

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

如果在属性文件中将同一属性定义为系统属性,则将应用系统属性。

假设我们将属性优先级定义为系统属性,其值为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.在地图中使用*@Value*

我们还可以使用*@Value注释来注入Map*属性。

首先,我们需要在我们的属性文件中以*{key: ‘value’ }*形式定义属性:

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

请注意,*Map*中的值必须用单引号括起来。

现在我们可以从属性文件中将此值作为Map注入:

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

如果我们需要获取特定键值地图,我们所要做的就是在表达式中添加键值的名称

@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;

映射*条目也可以在注入之前过滤*。

假设我们只需要获取那些值大于 1 的条目:

@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*注释与文件中定义的简单属性、系统属性以及使用 SpEL 表达式计算的属性一起使用的各种可能性。