报错记录:构造方法获取不了@Value的值,问题刨析与解决方案

报错记录:构造方法获取不了@Value的值,问题刨析与解决方案

有时我们需要在构造函数中初始化属性,之前老的项目是用的I/O流来获取配置文件的值,目前配置转为线上,使用Apollo来获取值,由于获取Apollo的值被封装到了Spring容器中,我们就需要使用Spring容器中的配置值

而获取配置最简单的方式就是使用@Value注解,但是老的项目中使用构造方法来初始化kafka的配置信息,这里项目初始化就会报错,debug后,发现获取的配置文件信息为null,导致bug出现

原因是:对象被Spring容器接管之前会调用构造函数构造对象,导致注解失效,构造函数执行完成被Spring容器接管之后才会调用@Value注解将配置注入对应的属性当中

下面是解决方案

一、查看Spring容器接管对象时的执行顺序

1、A.java

@Component
public class A {
    public A(){
        System.out.println("构造函数");
    }
    public void Test(){
        System.out.println("Test");
    }
}

2、测试类ATest.java

@SpringBootTest
public class ATest {
    @Autowired
    private A a;

    @Test
    public void TestA(){
        a.Test();
    }
}

3、结果

在这里插入图片描述

二、查看到底是配置文件没有对应的值还是说@Value注解没生效

1、在配置文件中有两个值

num=1
url="http://localhost:8080/test"

2、改造一下A.java类,看看普通方法

@SpringBootTest
public class ATest {
    @Value("${num}")
    private int num;

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

    @Value("${url:测试}")
    private String url2;

    @Value("${url3:测试默认值}")
    private String url3;

    @Autowired
    private A a;

    public A(){
        System.out.println("===========构造函数================");
        System.err.println(num);
        System.err.println(url);
        System.err.println(url2);
        System.err.println(url3);
    }
    public void Test(){
        System.out.println("===========Test方法================");
        System.err.println(num);
        System.err.println(url);
        System.err.println(url2);
        System.err.println(url3);
    }
}

2、运行测试类ATest.java的Test方法

@SpringBootTest
public class ATest {
    @Autowired
    private A a;

    @Test
    public void TestA(){
        a.Test();
    }
}

3、结果@Value没有生效,当然@ConfigurationProperties也不会生效

(1)、@Value注解

在这里插入图片描述

(2)、@ConfigurationProperties注解,我这里打了个断点直接看整个Animal.java类,这个类我没有放到本文的里面,没有必要,反正不行就对了

在这里插入图片描述

4、结论

由于基本数据类型int的默认值为0,而String是一个类,默认值就是null

url3url2这两个属性中的@Value注解我加入了默认值,如果@Value生效了,且在配置文件中找不到值,那么返回的则是默认值

而此处四个属性都返回的基本的默认值,说明执行构造函数的时候,Spring并没有接管该对象,导致@Value注解根本就没有生效

三、解决方案:使用@PostConstruct注解

在这里插入图片描述

1、改造A.java

@Component
public class A {

    @Value("${num}")
    private int num;

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

    @Value("${url:测试}")
    private String url2;

    @Value("${url3:测试默认值}")
    private String url3;

    public A(){
        System.out.println("===========构造函数================");
        System.err.println(num);
        System.err.println(url);
        System.err.println(url2);
        System.err.println(url3);
    }
    public void Test(){
        System.out.println("===========Test方法================");
        System.err.println(num);
        System.err.println(url);
        System.err.println(url2);
        System.err.println(url3);
    }
    @PostConstruct
    public void initField(){
        System.out.println("===========构造函数结束之后自动执行================");
        System.err.println(num);
        System.err.println(url);
        System.err.println(url2);
        System.err.println(url3);
    }
}

2、执行测试类ATest.java

@SpringBootTest
public class ATest {
    @Autowired
    private A a;

    @Test
    public void TestA(){
        a.Test();
    }
}

3、结果

在这里插入图片描述

这里有关于@PostConstruct注解的详解有兴趣的小伙伴可以看一下:Spring框架@PostConstruct注解详解 - 掘金 (juejin.cn)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

我认不到你

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

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

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

打赏作者

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

抵扣说明:

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

余额充值