@Value的用法
目录
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注解
1 从一个例子开始
假如在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注解时的属性名必须与配置文件属性名一致吗?
是的,如果不一致启动时直接报错。
2 @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文件中配置同名的系统属性,则服务启动时也就不会报错
3 通过@Value注入static 类型的属性
前面我们已经见识过,如何使用@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用在方法上的场景其实不多
运行结果
4 @Value支持的注入类型
上面的内容,都是用的字符串类型的变量进行举例的。其实,@Value注解还支持其他多种类型的系统属性值的注入。
4.1基本类型
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*/
}
有了这些常用的数据类型,我们在定义变量类型时,可以非常愉快的使用了,不用做额外的转换。
4.2数组
定义一个数组属性
@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时使用表达式
4.3 集合类
4.3.1 List
定义一个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<String> list;
/*setter and getter */
}
application.properties
person.name=liq person.staticpro=staticproValue person.hobbiess=game tv sing person.list=basketball tennis swim
测试结果
4.3.2 Map
定义一个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<String> list;
@Value("#{${person.map}}")
private Map<String,Object> 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"}
测试结果
4.3.3 Set
Set和List极为相似,不在赘述。这里说一下@Value如何为list和Map注入默认值
List属性注入默认值:
测试默认值
4.3.4 时间类型属性
4.3.5 获取系统属性
4.4注入Bean
以前我们注入bean,一般都是用的@Autowired或者@Resource注解。例如:
用@Value注解也可以注入bean,举例如下:
4.5调用静态类
5 ${}和#{}的区别
5.1 ${}
${}主要用于获取配置文件中的系统属性值。
例如:
@Value(value = "${person.name}")
private String name;
可以设置默认值。如果在配置文件中找不到person.name的配置,则注入时用默认值。
如果在配置文件中找不到person.name的配置,也没有设置默认值,则启动项目时会报错
5.2 #{}
#{}主要用于通过spring的EL表达式,获取bean的属性,或者调用bean的某个方法。还有调用类的静态常量和静态方法。
6 项目结构
maven项目POM
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.XX</groupId> <artifactId>LearnSpringBoot2-javaproject</artifactId> <version>1.0-SNAPSHOT</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.4.RELEASE</version> </parent> <dependencies> <!-- springboot java 项目 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> </dependency> </dependencies> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
项目目录结构
将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: 某某县
CSDN-Ada助手: 恭喜你开始博客创作!标题很吸引人,特别是对于那些遇到类似问题的Windows Server 2012 R2用户来说。你提到的无法更改系统时间的问题是一个很常见的困扰,对读者来说一定会有很大帮助。接下来,我建议你可以进一步探讨一些解决该问题的方法,比如通过命令行或注册表进行修改,或者检查是否权限设置有问题。希望你能继续分享更多有价值的技术文章,相信你的博客会越来越受欢迎的! 推荐【每天值得看】:https://bbs.csdn.net/forums/csdnnews?typeId=21804&utm_source=csdn_ai_ada_blog_reply1
adscici: kylin v10 ram架构下,按此文档安装成功!
CSDN-Ada助手: 恭喜你写了第三篇博客!看到你分享关于"@PropertySource"注解的使用,我觉得你的文章很有深度和实用性。你的解释很清晰,让初学者也能够理解这个注解的作用和用法。我真的很期待你未来的创作。不过,如果我可以提供一个建议的话,希望你能够在下一篇文章中探讨一下如何在实际项目中使用这个注解,以及它的一些常见陷阱和解决方法。谢谢你的分享,期待你的下一篇博客! CSDN 正在通过评论红包奖励优秀博客,请看红包流:https://bbs.csdn.net/?type=4&header=0&utm_source=csdn_ai_ada_blog_reply3
CSDN-Ada助手: 恭喜您撰写了第5篇博客!标题中提到的Spring中的BeanDefinition及其实现和BeanDefinitionReader的话题非常有深度。您的文章对于理解Spring框架中的核心概念起到了很好的指导作用。在下一步的创作中,或许您可以考虑探讨一些与BeanDefinition相关的高级主题,比如如何自定义BeanDefinition、Bean的生命周期管理等。期待您在未来的博客中继续分享有关Spring框架的知识,谢谢您的努力与分享!
CSDN-Ada助手: 恭喜您写了第四篇博客!标题很吸引人,我对您在麒麟操作系统ARM64架构下安装mysql5.7.22的经验非常感兴趣。希望您能继续分享更多的技术经验和学习心得。对于下一步的创作建议,我建议您可以考虑介绍如何优化mysql的性能或者如何与其他软件或框架进行集成。谢谢您的分享,期待您的下一篇博客! 如何快速涨粉,请看该博主的分享:https://hope-wisdom.blog.csdn.net/article/details/130544967?utm_source=csdn_ai_ada_blog_reply5