本期目录
- 一、 问题背景
- 二、 问题原因
- 三、 解决方法
一、 问题背景
今天碰到的问题是用 @Value
注解无法注入配置文件 application.yml
中的配置值。
检查过该类已经交给 Spring 容器管理了,即已经在类上加了 @Configuration
和 @ConfigurationProperties(prefix = "xxx")
注解了。但还是注入失败。
下面是配置文件 application.yml
中要注入的配置值:
student:
name: Tom
age: 21
问题伪代码如下:
@Configuration
@ConfigurationProperties(prefix = "student")
public class StudentConfig {
@Value("${student.name}")
private String name;
@Value("${student.age}")
private int age;
private Map<Long, Student> stuMap = new HashMap<>();
// 使用空参构造器初始化stuMap
public StudentConfig() {
stuMap.put(1001L, new Student(name, age));
}
}
看起来没有问题,但当我获取 stuMap
中的 Student
对象时,却发现其两个属性 name
为 null
、age
= 0 。
我明明已经通过 @Value
注入配置文件 application.yml
中的值了呀,为什么会注入失败呢?
二、 问题原因
上面的代码之所以注入失败,错误点在于我使用了构造器来初始化 stuMap
。要知道为什么,首选要知道 Spring 容器中 Bean 的生命周期。
Spring 创建 Bean 的过程如下:
构造器 --> 自动注入 (包括 @Value
和 @Autowired
) --> @PostConstruct
修饰的初始化方法
从上面的执行顺序就不难看出,构造器中的方法首先被执行,此时两个属性 name
和 age
都还没被注入呢,自然就是 null
和 0 ;构造器方法执行完毕后,才到自动注入,这时候两个属性 name
和 age
才被赋值,但已经晚了。
三、 解决方法
根据Spring 创建 Bean 的执行顺序:
构造器 --> 自动注入 (包括 @Value
和 @Autowired
) --> @PostConstruct
修饰的初始化方法
只要把原来写在构造器中的初始化代码,写到一个用 @PostConstruct
修饰的方法中即可。
修改后的代码就能成功注入配置文件 application.yml
中的值了。
@Configuration
@ConfigurationProperties(prefix = "student")
public class StudentConfig {
@Value("${student.name}")
private String name;
@Value("${student.age}")
private int age;
private Map<Long, Student> stuMap = new HashMap<>();
// 使用@PostConstruct注解初始化stuMap
@PostConstruct
public void initStuMap() {
stuMap.put(1001L, new Student(name, age));
}
}
以上就是我工作中遇到的问题了,希望对你有帮助。