I'm using Spring Framework 4.3 without Spring Boot. As far as I understand about the bean lifecycle :
- load bean definitions
- process bean definitions using beanFactoryPostProcessor classes
- instanciate and inject beans (loop with the right order)
- use beans
- let the garbage collector destroy beans
PropertyPlaceholderConfigurer
is a BeanFactoryPostProcessor
.
so @Value
properties must be read before instanciating beans. (step 2).
this is my code, Main class :
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;
}
}
Config class :
@Configuration
@ComponentScan(basePackages={"tn.esprit.beans"})
public class AppConfig {
//it works well without declaring this bean.
// @Bean
// public static PropertySourcesPlaceholderConfigurer placeHolderConfigurer() {
// return new PropertySourcesPlaceholderConfigurer();
// }
}
and finally my properties file under src/main/resources/db :
url=jdbc:mariadb://localhost:3306/client_project
When I run main class I get this output :
url constructor : null
url postconstruct : jdbc:mariadb://localhost:3306/client_project
Main : jdbc:mariadb://localhost:3306/client_project
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 ?
Is something wrong with my code? or with my understanding of bean lifecycle?