基本用法@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;// 指定默认值,如果配置文件中找不到相应的 key,则使用默认值@Value("${demo-cfg.basic.string:defaultValue}")private String stringValueWithDefaultValue;// 指定默认值为空字符串(即长度为 0 的字符串)@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;构造方法@Componentpublic class DemoComponent { private String stringValue; @Autowired public DemoComponent(@Value("${demo-cfg.basic.string}") String stringValue) { this.stringValue = stringValue; }}setter 方法@Componentpublic 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) { // 此处将 byte[] 数组中的 byte 转换成 int 类型后再打印,避免打印出的是乱码字符 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));}基本类型JavaYAMLOutput@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: trueintegerValue = 12345integerHex = 703710integerOct = 5349integerBin = 204longValue = 3405691582floatValue = 123.456doubleValue = 12.3456789charValue = abyteValue = 68shortValue = 12345booleanValue = 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;包装类型JavaYAMLOutput@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: trueintegerWrapper = 12345longWrapper = 3405691582floatWrapper = 123.456doubleWrapper = 12.3456789charWrapper = abyteWrapper = 68shortWrapper = 12345booleanWrapper = true注意:与基本类型一样,如果配置中相应的 key 不存在,那么 @Value 注解中必须要指定默认值,否则会报错;但当 key 对应的 value 值设置为空(空字符串或者空白字符)时,包装类型的值为 null.
数组类型JavaYAMLOutput@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, truestringArray = [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
List类型与数组类型类似,只是 List 类型的元素类型只支持包装类型,不支持基本类型。
JavaYAMLOutput@Value("${demo-cfg.advanced.array.string}")private List
总结本文对 Spring 的 @Value 注解的使用进行了比较完整的介绍,初级用法中分别对基本类型、包装类型、数组类型、List 类型的注入给出了示例,高级用法中对 @Value 注解中如何使用 SpEL 表达式进行了简单介绍。