当前位置: 首页 > 知识库问答 >
问题:

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

南门飞
2023-03-14

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

    < li >加载bean定义 < li >使用beanFactoryPostProcessor类处理bean定义 < li >实例化并注入beans(以正确的顺序循环) < li >使用豆子 < li >让垃圾收集器销毁豆子

PropertyPlaceholderConfigurer是一个BeanFactoryPostProcessor。因此,@Value属性必须在声明bean之前读取。(步骤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());
}

读取值从文件.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/主/资源/db 下:

url=jdbc:mariadb://localhost:3306/client_project

当我运行main class时,我得到了这个输出:

url constructor : null
url postconstruct : jdbc:mariadb://localhost:3306/client_project
Main : jdbc:mariadb://localhost:3306/client_project

当spring调用这个构造函数时,url属性为空!如果在实例化beans之前必须读取< code>@Value属性,那么url必须设置为不同于null。

不是吗?

我的代码有问题吗?或者根据我对bean生命周期的理解?

共有1个答案

东郭俊楠
2023-03-14

当Spring调用此构造函数时,url 属性为空 !如果@Value属性必须在实例化 bean 之前读取,因此必须设置 url 并且与 null 不同。不是吗?

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

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

您的代码没有任何问题。

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

    < Li > < code > Constructor inject-表示在用于注入的依赖项实例化期间必须存在依赖项/值 < li> Setter注入-表示在依赖项实例化期间不需要依赖项/值,但将在以后使用Setter方法注入 < li> Field注入-表示依赖项/值在依赖项实例化期间不是必需的,但将在以后使用反射注入
 类似资料:
  • 问题内容: 在哪里进行调用将使我的状态失水的API调用的最佳位置是哪里?构造函数或生命周期方法之一,例如ComponentWillMount? 问题答案: 最好从生命周期方法进行api调用,反应文档也建议相同。 根据DOC: componentDidMount: 挂载组件后立即调用componentDidMount()。需要DOM节点的初始化应该在这里进行。 如果需要从远程端点加载数据,这是实例化

  • 忽视省略(elision)情况,带上生命周期的函数签名(function signature)有一些限制: 任何引用都必须拥有标注好的生命周期。 任何被返回的引用都必须有一个和输入量相同的生命周期或是静态类型(static)。 另外要注意,若会导致返回的引用指向无效数据,则返回不带输入量的引用是被禁止的。下面例子展示了一些带有生命周期的函数的有效形式: // 一个拥有生命周期 `'a` 的输入引用

  • 本文向大家介绍react生命周期函数相关面试题,主要包含被问及react生命周期函数时的应答技巧和注意事项,需要的朋友参考一下 这个问题要考察的是组件的生命周期 一、 初始化阶段: Constructor初始化状态 componentWillMount:组件即将被装载、渲染到页面上 render:组件在这里生成虚拟的DOM节点 componentDidMount:组件真正在被装载之后 二、 运行中

  • 掌握构建生命周期 作为一个构建脚本的开发者,你不应该局限于编写任务动作或者配置逻辑,有时候你想在指定的生命周期事件发生的时候执行一段代码。生命周期事件可以在指定的生命周期之前、之中或者之后发生,在执行阶段之后发生的生命周期事件就该是构建的完成了。 假设你希望在构建失败时能够在开发阶段尽早得到反馈,给构建生命周期事件添加回调有两种方法:一是通过闭包,二是实现 Gradle API 的一个监听接口,G

  • 因此,由于我一直在使用spring,如果我要编写一个具有依赖项的服务,我将执行以下操作: 我现在运行了使用另一个约定来实现相同目标的代码 这两种方法都会奏效,我明白。但是使用选项B有什么好处吗?对我来说,它在类和单元测试中创建了更多的代码。(必须编写构造函数,不能使用@InjectMocks) 是不是我漏了什么?autowired构造函数除了向单元测试添加代码之外,还有其他的功能吗?这是一种更好的

  • 我想用构造函数注入将一个bean列表注入到一个spring bean中。 但是BeanToInject的实现在其他模块中。这些模块可能被关闭。如果applicationcontext中没有BeanToInject的实现,则spring在start上抛出异常,而不是注入空列表。我能做什么?(对我来说,基于设置器和私有财产的自动取舍不是一种选择。)