基本用法
@Value
注解支持从 Properties
配置文件或者 YAML
配置文件中读取配置并注入到 bean
中,鉴于 YAML
配置的比 Properties
配置更有层次,功能也更强大,本文中均以 YAML
配置文件为例进行说明。
@Value("This is a literal string value") private String literalStringValue;
@Value("${demo-cfg.basic.string}") private String stringValue;
@Value("${demo-cfg.basic.string:defaultValue}") private String stringValueWithDefaultValue;
@Value("${demo-cfg.basic.string:}") private String stringValueWithDefaultEmptyString;
|
注意:使用 @Value
注解的类必须是 Spring 管理的 bean,即:该类上面配置有下面任意一种注解:@Component
, @Service
, @Controller
, @RestController
, @Configuration
.
三种注入方式
@Value 注解支持三种注入方式:实例属性、构造方法、setter 方法。
实例属性
@Value("${demo-cfg.basic.string}") private String stringValue;
|
构造方法
@Component public class DemoComponent { private String stringValue;
@Autowired public DemoComponent(@Value("${demo-cfg.basic.string}") String stringValue) { this.stringValue = stringValue; } }
|
setter 方法
@Component public class DemoComponent { private String stringValue; @Autowired public void setStringValue(@Value("${demo-cfg.basic.string}") String stringValue) { this.stringValue = stringValue; } }
|
一般推荐使用实例属性注入方式,比较简洁。
初级用法
由于字符串类型已经在基本用法中介绍过,此处不再赘述。下面对基本类型、包装类型、数组类型、List类型分别举例如何使用 @Value
注解。为了便于比对,采用三个 Tab页分别放置 Java代码、YAML配置、变量结果打印。Java变量结果打印的方法如下:
private static void print(String name, Object value) { if (value instanceof byte[]) { byte[] byteArray = (byte[]) value; int[] tempIntArray = new int[byteArray.length]; for (int i = 0; i < byteArray.length; i++) { tempIntArray[i] = byteArray[i]; } value = tempIntArray; } System.out.println(StrUtil.format("{} = {}", StrUtil.padAfter(name, 12, StrUtil.C_SPACE), value)); }
|
基本类型
@Value("${demo-cfg.basic.integer}") private int integerValue;
@Value("${demo-cfg.basic.integerHex}") private int integerHex;
@Value("${demo-cfg.basic.integerOct}") private int integerOct;
@Value("${demo-cfg.basic.integerBin}") private int integerBin;
@Value("${demo-cfg.basic.long}") private long longValue;
@Value("${demo-cfg.basic.float}") private float floatValue;
@Value("${demo-cfg.basic.double}") private double doubleValue;
@Value("${demo-cfg.basic.char}") private char charValue;
@Value("${demo-cfg.basic.byte}") private byte byteValue;
@Value("${demo-cfg.basic.short}") private short shortValue;
@Value("${demo-cfg.basic.boolean}") private boolean booleanValue;
|
demo-cfg: basic: integer: 12345 integerHex: 0xABCDE integerOct: 012345 integerBin: 0b11001100 long: 0xCAFEBABE float: 123.456 double: 12.3456789 char: a byte: 68 short: 12345 boolean: true
|
integerValue = 12345 integerHex = 703710 integerOct = 5349 integerBin = 204 longValue = 3405691582 floatValue = 123.456 doubleValue = 12.3456789 charValue = a byteValue = 68 shortValue = 12345 booleanValue = true
|
注意:对于基本类型,如果配置中相应的 key
不存在,那么 @Value
注解中必须要指定默认值,否则会报错;或者即使相应的 key
存在,但是对应的 value
没有设置或格式错误,也会报错。
@Value("${demo-cfg.basic.integer:16888}") private int integerValue;
@Value("${demo-cfg.basic.float:1.23}") private float floatValue;
@Value("${demo-cfg.basic.boolean:true}") private boolean booleanValue;
|
包装类型
@Value("${demo-cfg.basic.integer}") private Integer integerWrapper;
@Value("${demo-cfg.basic.long}") private Long longWrapper;
@Value("${demo-cfg.basic.float}") private Float floatWrapper;
@Value("${demo-cfg.basic.double}") private Double doubleWrapper;
@Value("${demo-cfg.basic.char}") private Character charWrapper;
@Value("${demo-cfg.basic.byte}") private Byte byteWrapper;
@Value("${demo-cfg.basic.short}") private Short shortWrapper;
@Value("${demo-cfg.basic.boolean}") private Boolean booleanWrapper;
|
demo-cfg: basic: integer: 12345 long: 0xCAFEBABE float: 123.456 double: 12.3456789 char: a byte: 68 short: 12345 boolean: true
|
integerWrapper = 12345 longWrapper = 3405691582 floatWrapper = 123.456 doubleWrapper = 12.3456789 charWrapper = a byteWrapper = 68 shortWrapper = 12345 booleanWrapper = true
|
注意:与基本类型一样,如果配置中相应的 key
不存在,那么 @Value
注解中必须要指定默认值,否则会报错;但当 key
对应的 value
值设置为空(空字符串或者空白字符)时,包装类型的值为 null
.
数组类型
@Value("${demo-cfg.advanced.array.string}") private String[] stringArray;
@Value("${demo-cfg.advanced.array.integer}") private int[] integerArray;
@Value("${demo-cfg.advanced.array.long}") private long[] longArray;
@Value("${demo-cfg.advanced.array.float}") private float[] floatArray;
@Value("${demo-cfg.advanced.array.double}") private double[] doubleArray;
@Value("${demo-cfg.advanced.array.char}") private char[] charArray;
@Value("${demo-cfg.advanced.array.byte}") private byte[] byteArray;
@Value("${demo-cfg.advanced.array.short}") private short[] shortArray;
@Value("${demo-cfg.advanced.array.boolean}") private boolean[] booleanArray;
|
demo-cfg: advanced: array: string: Big Bang Theory, Sheldon Cooper integer: 1234, 56789 long: 0xCAFEBABE, 0xDEADBEEF float: 1.2, 3.45, 6.789 double: 1.23456789, 2.3456789, 3.45678912345 char: abc byte: -12, 67, 89 short: 12345, 23456, 32767 boolean: true, false, true
|
stringArray = [Big Bang Theory, Sheldon Cooper] integerArray = [1234, 56789] longArray = [3405691582, 3735928559] floatArray = [1.2, 3.45, 6.789] doubleArray = [1.23456789, 2.3456789, 3.45678912345] charArray = [a, b, c] byteArray = [-12, 67, 89] shortArray = [12345, 23456, 32767] booleanArray = [true, false, true]
|
注意:数组元素类型也可以是包装类型。另外,数组类型配置的值默认是由逗号分隔符(英文半角)进行分隔,逗号分隔符前后可以有若干空白字符,不会影响解析。如果希望分隔符是其它符号,则需要用到高级用法中的 SpEL
,参见后面高级用法之 使用 Spring 表达式 SpEL 。
例外:char[]
类型的数组,配置值不能是逗号分隔的如 “a, b, c” 这样的值,否则注入进来得到的 char[]
是一个长度为 7 的数组,其值为 ['a', ',', ' ', 'b', ',', ' ', 'c']
,即中间的逗号和空格都被算作一个 char
注入 char[]
数组中了。对于包装类型数组 Character[]
和下面的 List
类型 List<Character>
, 其值仍然是用逗号分隔。
List类型
与数组类型类似,只是 List
类型的元素类型只支持包装类型,不支持基本类型。
@Value("${demo-cfg.advanced.array.string}") private List<String> stringList;
@Value("${demo-cfg.advanced.array.integer}") private List<Integer> integerList;
@Value("${demo-cfg.advanced.array.long}") private List<Long> longList;
@Value("${demo-cfg.advanced.array.float}") private List<Float> floatList;
@Value("${demo-cfg.advanced.array.double}") private List<Double> doubleList;
@Value("${demo-cfg.advanced.array.char}") private List<Character> charList;
@Value("${demo-cfg.advanced.array.byte}") private List<Byte> byteList;
@Value("${demo-cfg.advanced.array.short}") private List<Short> shortList;
@Value("${demo-cfg.advanced.array.boolean}") private List<Boolean> booleanList;
|
demo-cfg: advanced: array: string: Big Bang Theory, Sheldon Cooper integer: 1234, 56789 long: 0xCAFEBABE, 0xDEADBEEF float: 1.2, 3.45, 6.789 double: 1.23456789, 2.3456789, 3.45678912345 char: a, b, c byte: -12, 67, 89 short: 12345, 23456, 32767 boolean: true, false, true
|
stringList = [Big Bang Theory, Sheldon Cooper] integerList = [1234, 56789] longList = [3405691582, 3735928559] floatList = [1.2, 3.45, 6.789] doubleList = [1.23456789, 2.3456789, 3.45678912345] charList = [a, b, c] byteList = [-12, 67, 89] shortList = [12345, 23456, 32767] booleanList = [true, false, true]
|
高级用法
使用 Spring 表达式 SpEL
@Value("#{'${demo-cfg.advanced.spel.short}'.split('\\s*__\\s*')}") private List<Short> shortListSpEL;
@Value("#{systemProperties['priority']}") private Integer priority;
@Value("#{systemProperties['priority'] ?: '123'}") private Integer priorityWithDefault;
|
demo-cfg: advanced: spel: short: 12345 __ 23456 __ 32767
|
shortListSpEL = [12345, 23456, 32767] priority = null priorityWithDefault = 123
|
利用 SpEL 注入 Map
@Value("#{${demo-cfg.advanced.spel.map}}") private Map<String, String> configMap;
|
demo-cfg: advanced: spel: map: '{ host: "192.168.88.168", port: "3306", username: "Sheldon", password: "Cooper" }'
|
configMap = {host=192.168.88.168, port=3306, username=Sheldon, password=Cooper}
|
注意:YAML 配置中 map
类型的值必须是 JSON
格式的字符串(最外层的引号为单引号或双引号都可以,外层为单引号,则 JSON
内部用双引号,反之亦然)。
总结
本文对 Spring
的 @Value
注解的使用进行了比较完整的介绍,初级用法中分别对基本类型、包装类型、数组类型、List 类型的注入给出了示例,高级用法中对 @Value
注解中如何使用 SpEL
表达式进行了简单介绍。