Spring Bean生命周期-@value属性在构造函数中为null

时间:2019-03-04 16:52:58

标签: java spring

我正在使用没有Spring Boot的Spring Framework 4.3。 据我对bean生命周期的了解:

  1. 加载bean定义
  2. 使用beanFactoryPostProcessor类处理bean定义
  3. 实例化并注入bean(以正确的顺序循环)
  4. 使用豆子
  5. 让垃圾收集器摧毁豆子

PropertyPlaceholderConfigurerBeanFactoryPostProcessor。 因此必须在实例化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生命周期的了解?

1 个答案:

答案 0 :(得分:4)

  

spring调用此构造方法时,url属性为null!如果必须在实例化bean之前读取@Value属性,则必须设置url且该URL不同于null。是吗?

这不是它的工作方式,如果ReadValueFromFile的构造函数需要@Value,那么只有Spring会保证在实例化ReadValueFromFile之前url值可用,否则Spring实例化ReadValueFromFile使用默认构造函数,然后调用setter属性的url方法,它将注入该值。

因此,在构造函数运行期间,您将看不到该值。

您的代码没有错。

您需要了解Spring如何注入依赖项(或值):

  1. Constructor注入-意味着在注入的依赖实例化期间必须存在依赖关系/值
  2. Setter注入-表示在依赖实例化过程中不需要依赖项/值,但稍后将使用setter方法注入
  3. Field注入-表示在依赖实例化过程中不需要依赖项/值,但是稍后将使用反射注入