首页 > 解决方案 > 为什么@Value 作为构造函数的参数正确填充属性?

问题描述

我的问题是:为什么这段代码正确设置了构造函数参数属性port

private final RedisServer redisServer;

public RedisTestConfiguration(@Value("${cache.port}") final int port) {
   this.redisServer = new RedisServer(port);
}

据我了解,@Value("${cache.port}")由称为 AutowiredAnnotationBeanPostProcessor 的 BeanPostProcessor 解决。Spring bean 生命周期的工作方式是在任何 BeanPostProcess 之前调用构造函数方法,见下图。注意构造函数在 BeanPostProcessor.postProcessBeforeInitialization() 之前调用。

Spring Bean 生命周期

这怎么还能用?

问候,

巴特

标签: javaspringspring-boot

解决方案


PropertySourcesPlaceholderConfigurer 支持此行为

参考:https ://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-factory-placeholderconfigurer

PropertySourcesPlaceholderConfigurer 是一个 BeanFactoryPostProcessor。它收集 @Value 字段并更新 Spring 容器中的 bean 定义。在初始化任何 bean 之前,应在容器中创建 PropertySourcesPlaceholderConfigurer。

文档中描述了 Bean 元数据: https ://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-factory-metadata

因此,流程如下: 1. Bean 定义阅读器从 xml 文件或 java 类中收集 bean 声明。例如,XmlBeanDefinitionReader。

参考:https ://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/beans/factory/xml/XmlBeanDefinitionReader.html

  1. Bean Factory Post Processors 更新 bean 定义。例如,PropertySourcesPlaceholderConfigurer。

  2. Spring 容器查看 bean 定义并根据 bean 定义值创建 bean(调用构造函数)。参考:https ://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-factory-class

所以,问题是这 As of my understanding, @Value("${cache.port}") is resolved by a BeanPostProcessor是不正确的。@Value 由 BeanFactoryPostProcessor 管理,而不是 BeanPostProcessor

实际上,文档指出:

A default lenient embedded value resolver is provided by Spring. It will try to resolve the property value and if it cannot be resolved, the property name (for example ${catalog.name}) will be injected as the value. If you want to maintain strict control over nonexistent values, you should declare a PropertySourcesPlaceholderConfigurer bean, as the following example shows:...

Spring 有某种默认属性解析器,即另一个 BeanFactoryPostProcessor。但是可以用 PropertySourcesPlaceholderConfigurer 覆盖它


推荐阅读