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

标签 java spring

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

  1. 加载bean定义
  2. 使用 beanFactoryPostProcessor 类处理 bean 定义
  3. 实例化并注入(inject) Bean(以正确的顺序循环)
  4. 使用 bean
  5. 让垃圾收集器销毁 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)依赖项(或值):

  1. 构造函数注入(inject) - 意味着在注入(inject)的依赖实例化期间必须存在依赖项/值
  2. Setter 注入(inject) - 意味着在依赖实例化期间不需要依赖项/值,但稍后将使用 setter 方法注入(inject)
  3. Field 注入(inject) - 意味着在依赖实例化期间不需要依赖项/值,但稍后将使用反射注入(inject)

关于java - Spring Bean 生命周期 - 构造函数中的 @value 属性为 null,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54987934/

相关文章:

Spring @MVC和@RequestParam验证

spring - 有没有办法从 CXF 中的 JAX-RS REST 资源访问 CXF 消息交换?

java - 如何创建包含 Java 类层次结构的字典(在 Python 中)?

java - 为什么我无法初始化通用参数和数组?

java - 比较java列表

java - 需要帮助计算 MaxHeap 中的交换数量

java - MongoDB 和 Spring MVC : PATCH operation?

spring - Neo4j/SDN 警告 : No identity field found for class of type for exception class

spring - Liquibase Hibernate 不一致

java - 替换字符串中的字符而不使用 if else