我使用的是 Spring Framework 4.3,没有 Spring Boot。 据我了解 bean 生命周期:
- 加载bean定义
- 使用 beanFactoryPostProcessor 类处理 bean 定义
- 实例化并注入(inject) Bean(以正确的顺序循环)
- 使用 bean
- 让垃圾收集器销毁 Bean
PropertyPlaceholderConfigurer
是一个BeanFactoryPostProcessor
。
因此在实例化 bean 之前必须读取 @Value
属性。 (步骤 2)。
这是我的代码, 主类:
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
ReadValueFromFile dc = ctx.getBean(ReadValueFromFile.class);
System.out.println("Main : " + dc.getUrl());
}
ReadValueFromFile.java
@Component
@PropertySource("classpath:db/db.properties")
public class ReadValueFromFile {
@Value("${url}")
private String url;
public ReadValueFromFile() {
System.out.println("url constructor : " + url);
}
@PostConstruct
void init() {
System.out.println("url postconstruct : " + url);
}
@PreDestroy
void dest() {
System.out.println("url @PreDestroy : " + url);
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
配置类:
@Configuration
@ComponentScan(basePackages={"tn.esprit.beans"})
public class AppConfig {
//it works well without declaring this bean.
// @Bean
// public static PropertySourcesPlaceholderConfigurer placeHolderConfigurer() {
// return new PropertySourcesPlaceholderConfigurer();
// }
}
最后是 src/main/resources/db 下的属性文件:
url=jdbc:mariadb://localhost:3306/client_project
当我运行主类时,我得到以下输出:
url constructor : null
url postconstruct : jdbc:mariadb://localhost:3306/client_project
Main : jdbc:mariadb://localhost:3306/client_project
当spring调用这个构造函数时,url属性为null!
如果在实例化 bean 之前必须读取 @Value
属性,则必须设置 url,并且不能为 null。
不是吗?
我的代码有问题吗?或者我对 bean 生命周期的理解?
最佳答案
When spring invoke this constructor, url attribute is null ! if @Value properties must be read before instanciating beans, so the url must be set and different from null. isn't it ?
这不是它的工作原理,如果 ReadValueFromFile
的构造函数需要 @Value
那么只有 Spring 会保证在实例化 ReadValueFromFile
之前 >url
值可用,否则 Spring 使用默认构造函数实例化 ReadValueFromFile
,然后调用 url
属性的 setter
方法注入(inject)值。
因此,在构造函数运行期间您将看不到该值。
您的代码没有任何问题。
您需要了解 Spring 如何注入(inject)依赖项(或值):
构造函数
注入(inject) - 意味着在注入(inject)的依赖实例化期间必须存在依赖项/值Setter
注入(inject) - 意味着在依赖实例化期间不需要依赖项/值,但稍后将使用 setter 方法注入(inject)Field
注入(inject) - 意味着在依赖实例化期间不需要依赖项/值,但稍后将使用反射注入(inject)
关于java - Spring Bean 生命周期 - 构造函数中的 @value 属性为 null,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54987934/