Spring的@Value注解使用实践及一个经典的易错场景

前言

Spring提供了@Value注解帮助我们注入一个自定义属性或者对象,大大简化了我们的操作。但是如果对其原理不清楚,有时也会遇到一些不可预期的bug。

本文主要介绍了@Value注解使用的常见场景及使用方法,以及分享一个比较经典的易错场景。

如何使用

常见的使用方式有以下四种,请注意使用方式的不同。

//直接注入一个字符串
@Value("我是字符串")
private String str; 

//注入系统参数、环境变量或者配置文件中的值
//注意此处用的是 ${}
@Value("${application.name}")
private String applicationName;

//注入一个Bean的属性,其中person为bean的ID,name为其属性
//注意此处用的是 #{}
@Value("${person.name}")
private String name;

//注入一个bean,person是我们定义的一个bean
//注意注入bean时使用是 #{}
@Value("#{person}")
private Person person;

实践

1,注入一个字符串

@SpringBootApplication(scanBasePackages = "com.shishan.demo2023.*")
public class Demo2023Application {

    public static void main(String[] args) {
        SpringApplication.run(Demo2023Application.class, args);
    }

    @Value("我是常量字符串")
    private String str;

    @PostConstruct
    public void init() {
        //打印常量字符串
        System.out.println("str====" + str);
    }
}

启动我们的项目,可以看到控制台打印出我们注入的str的值:

2,注入一个自定义属性

在application.properties配置文件中配置以下属性:

spring.application.name=demo2023
server.port=8080
username=shishan
userpassword=123456
@SpringBootApplication(scanBasePackages = "com.shishan.demo2023.*")
public class Demo2023Application {

    public static void main(String[] args) {
        SpringApplication.run(Demo2023Application.class, args);
    }

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

    @PostConstruct
    public void init() {
        //打印自定义属性
        System.out.println("username====" + username);
    }
}

启动项目,控制台打印出来我们自定义的属性值:

3,注入一个bean

先定义一个bean,并通过@Bean注入Spring容器

@Data
public class Person {
    private String name;
    private Integer age;
}

@Component
public class PersonConfig {

    @Bean
    public Person person(){
        Person person = new Person();
        person.setName("男人or女人");
        person.setAge(18);
        return person;
    }
}

通过@Value注入person对象:

@SpringBootApplication(scanBasePackages = "com.shishan.demo2023.*")
public class Demo2023Application {

    public static void main(String[] args) {
        SpringApplication.run(Demo2023Application.class, args);
    }

    @Value("#{person}")
    private Person person;

    @PostConstruct
    public void init() {
        //打印自定义属性
        System.out.println("person====" + person);
    }
    
}

启动项目,可以看到控制台打印出了person对象的属性:

4,注入一个对象的属性

还以上面的person对象为例,使用@Value注入person.name。

public class Demo2023Application {

    public static void main(String[] args) {
        SpringApplication.run(Demo2023Application.class, args);
    }
    
    @Value("#{person.name}")
    private String personName;

    @PostConstruct
    public void init() {
        //打印personName
        System.out.println("personName====" + personName);
    }
}

启动项目,可以看到控制打印出了personName:

总结:使用@Value可以直接注入一个常量字符串,如果要注入一个自定义属性,请使用$符,如果要注入一个对象或者对象的属性,要使用#号。

重点:注入自定义属性用${},注入对象用#{}。

@Value容易出错的一个经典场景

当我们使用@Value注入一个自定义的属性值时,有一个容易出错的经典场景就是:我们自定义的属性与系统环境变量属性冲突了,系统环境变量会覆盖掉我们的自定义属性值,并且不会报错。

场景复现:

在application.properties配置文件中配置如下属性:

spring.application.name=demo2023
server.port=8080
//定义user.name为shishan
user.name=shishan

尝试注入user.name:

@SpringBootApplication(scanBasePackages = "com.shishan.demo2023.*")
public class Demo2023Application {

    public static void main(String[] args) {
        SpringApplication.run(Demo2023Application.class, args);
    }

    @Value("${user.name}")
    private String username;

    @PostConstruct
    public void init() {
        //打印username
        System.out.println("username====" + this.username);
    }
}

按照我们的预期,控制台应该打印出username=shishan,但是结果却不是这样的。

我们可以看到控制打印出的结果是usename====cc,cc是博主的电脑用户名。

之所以出现这样的结果,是因为user.name正好与博主的系统变量冲突了,Spring优先读取了系统变量,而忽略了我们的自定义变量。

Spring查找匹配变量时,采用的是策略是匹配即返回,并不会一直匹配到最后一个属性,我们可以在PropertySourcesPropertyResolver#getProperty方法中找到Spring匹配属性的逻辑,感兴趣的朋友可以翻阅源码看一看。

建议我们在自定义属性值时,可以使用比较独特的前缀,比如业务+属性名,尽量和一些重合度比较高的属性名避开,这样可以最大程度的避免这些错误。

最后

本文主要介绍了@Value注解的使用方法,及一个容易出错的写法。在实际业务场景中,一般用于读取自定义配置,提升代码的扩展性,方便后期的维护。

学习技术,分享技术,期待与大家共同进步,也感谢您的点赞与关注。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员拾山

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值