目录
前言
1 从一个例子开始
2 @Value注解的默认值
3 通过@Value注入static 类型的属性
4 @Value支持的注入类型
4.1基本类型
4.2数组
4.3 集合类
4.3.1 List
4.3.2 Map
4.3.3 Set
4.3.4 时间类型属性
4.3.5 获取系统属性
4.4注入Bean
4.5调用静态类
5 ${}和#{}的区别
5.1 ${}
5.2 #{}
6 项目结构
如果想要动态读取配置文件中的某个系统属性,可以使用@Value注解
假如在Person类中,需要注入系统属性到name变量中。通常情况下,我们会写出如下的代码:
@Component
public class Person {
@Value("${person.name}")
private String name;
/*setter and getter */
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
通过@Value注解指定系统属性的名称person.name,该名称需要使用${}包起来。
这样spring就会自动的帮我们把对应的系统属性值,注入到name变量中。
不过,上面功能的重点是要在application.properties文件(简称:配置文件)中配置同名的系统属性:
person.name=liname
那么,使用@Value注解时的属性名必须与配置文件属性名一致吗?
是的,如果不一致启动时直接报错。
比如有这样一个需求:如果配置了系统属性,name就用配置的属性值。如果没有配置,则name用默认值lisa。
有些朋友可能认为可以这样做:
applicaiton.properties
#person.name=li
@Component
public class Person {
@Value("${person.name}")
private String name="lisa";
/*setter and getter */
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
结果是启动报错
也就是在定义参数时直接给个默认值是行不通的的。因为设置name默认值的时机,比@Value注解依赖注入属性值要早,也就是说name初始化好了默认值,后面还是会读取person.name的值。
那么,到底该如何设置默认值呢?
答:使用 :
例如:
@Component
public class Person {
@Value("${person.name:lisa}")
private String name;
/*setter and getter */
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
在需要设置默认值的系统属性名后,加 : 符号。紧接着,在 : 右边设置默认值。
建议大家平时在使用@Value时,尽量都设置一个默认值。如果不需要默认值,宁可设置一个空。比如:
@Component
public class Person {
@Value("${person.name:}")
private String name;
/*setter and getter */
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
这样的话,如果不在.properties文件中配置同名的系统属性,则服务启动时也就不会报错
前面我们已经见识过,如何使用@Value注解,给类的成员变量注入系统属性值。
那么,问题来了,静态变量可以自动注入系统属性值不?
增加一个静态属性检验一下
@Component
public class Person {
@Value("${person.name:}")
private String name;
@Value("${person.staticpro:aa}")
public static String staticpro;
}
application.properties
person.name=liq person.staticpro=staticproValue
运行结果
程序可以正常启动,但是获取到的值却是null。
由此可见,被static修饰的变量通过@Value会注入失败。
如何才能给静态变量注入系统属性值呢?
操作如下:
@Component
public class Person {
@Value("${person.name:}")
private String name;
@Value("${person.staticpro:aa}")
public static String staticpro;
@Value("${person.staticpro:aa}")
public void setStaticpro(String staticpro) {
Person.staticpro = staticpro;
}
public static String getStaticpro() {
return staticpro;
}
/*setter and getter */
}
application.properties
person.name=liq person.staticpro=staticproValue
提供一个静态参数的setter方法,在该方法上使用@Value注入属性值,并且同时在该方法中给静态变量赋值。
此时@Value注解在这里竟然使用在setStaticpro方法上了,也就是对应的setter方法,而不是在变量上。
不过,通常情况下,我们一般会在pojo实体类上,使用lombok的@Data、@Setter、@Getter等注解,在编译时动态增加setter或getter方法,所以@Value用在方法上的场景其实不多
运行结果
上面的内容,都是用的字符串类型的变量进行举例的。其实,@Value注解还支持其他多种类型的系统属性值的注入。
Java中的基本数据类型有4类8种
整型:byte、short、int、long
浮点型:float、double
布尔型:boolean
字符型:char
相对应地提供了8种包装类:
整型:Byte、Short、Integer、Long
浮点型:Float、Double
布尔型:Boolean
字符型:Character
@Value注解对这8中基本类型和相应的包装类,有非常良好的支持,例如:
@Component
public class Person {
@Value("${person.name:}")
private String name;
@Value("${person.staticpro:aa}")
public static String staticpro;
@Value("${person.a:1}")
private byte a;
@Value("${person.b:100}")
private short b;
@Value("${person.c:1000}")
private int c;
@Value("${person.d:40000000}")
private long d;
@Value("${person.e:5.2}")
private float e;
@Value("${person.f:6.1}")
private double f;
@Value("${person.g:false}")
private boolean g;
@Value("${person.h:h}")
private char h;
@Value("${person.a}")
private Byte a1;
@Value("${person.b}")
private Short b1;
@Value("${person.c}")
private Integer c1;
@Value("${person.d}")
private Long d1;
@Value("${person.e}")
private Float e1;
@Value("${person.f}")
private Double f1;
@Value("${person.g}")
private Boolean g1;
@Value("${person.h}")
private Character h1;
/* setter and getter*/
}
有了这些常用的数据类型,我们在定义变量类型时,可以非常愉快的使用了,不用做额外的转换。
定义一个数组属性
@Component
public class Person {
@Value("${person.name:}")
private String name;
@Value("${person.staticpro:aa}")
public static String staticpro;
@Value("${person.hobbiess}")
private String[] hobbiess;
/*setter and getter */
}
application.properties
person.name=liq person.staticpro=staticproValue person.hobbiess=game,tv,sing
运行结果
spring默认使用逗号分隔参数值。
如果用空格分隔,例如:
application.properties
person.name=liq person.staticpro=staticproValue person.hobbiess=game tv sing
那么spring认为只有一个值
如果非要用非逗号做分割,比如上面用空格做分割,那么可以在@Value时使用表达式
定义一个List类型的属性
@Component
public class Person {
@Value("${person.name:}")
private String name;
@Value("${person.staticpro:aa}")
public static String staticpro;
//@Value("${person.hobbiess}")
@Value("#{'${person.hobbiess}'.split(' ')}")
private String[] hobbiess;
//注意sprlit()方法的分割类型要与application.properties中list用的分割类型一致。
@Value("#{'${person.list}'.split(' ')}")
private List list;
/*setter and getter */
}
application.properties
person.name=liq person.staticpro=staticproValue person.hobbiess=game tv sing person.list=basketball tennis swim
测试结果
定义一个Map类型的属性
@Component
public class Person {
@Value("${person.name:}")
private String name;
@Value("${person.staticpro:aa}")
public static String staticpro;
//@Value("${person.hobbiess}")
@Value("#{'${person.hobbiess}'.split(' ')}")
private String[] hobbiess;
//注意sprlit()方法的分割类型要与application.properties中list用的分割类型一致。
@Value("#{'${person.list}'.split(' ')}")
private List list;
@Value("#{${person.map}}")
private Map map;
/*setter and getter */
}
application.properties
person.name=liq person.staticpro=staticproValue person.hobbiess=game tv sing person.list=basketball tennis swim person.map={aa:"aa",bb:"bb"}
测试结果
Set和List极为相似,不在赘述。这里说一下@Value如何为list和Map注入默认值
List属性注入默认值:
测试默认值
以前我们注入bean,一般都是用的@Autowired或者@Resource注解。例如:
用@Value注解也可以注入bean,举例如下:
${}主要用于获取配置文件中的系统属性值。
例如:
@Value(value = "${person.name}")
private String name;
可以设置默认值。如果在配置文件中找不到person.name的配置,则注入时用默认值。
如果在配置文件中找不到person.name的配置,也没有设置默认值,则启动项目时会报错
#{}主要用于通过spring的EL表达式,获取bean的属性,或者调用bean的某个方法。还有调用类的静态常量和静态方法。
maven项目POM
4.0.0 org.XX LearnSpringBoot2-javaproject 1.0-SNAPSHOT org.springframework.boot spring-boot-starter-parent 2.3.4.RELEASE org.springframework.boot spring-boot-starter org.springframework.boot spring-boot-configuration-processor 8 8 UTF-8 org.springframework.boot spring-boot-maven-plugin
项目目录结构
将application.properties换成application.yml 结果一样
person: age: 27 name: scy staticpro: staticproValue hobbiess: game,tv,sing list: basketball tennis swim map: '{ aa: "aaa",bb: "bbb"}' birthday: 2022-01-07 12:12:12 address: province: 某某省 distinct: 某某市 county: 某某县