Spring @Value 配置项解析 vs Spring @ConfigurationProperties 配置项解析

@ConfigurationProperties 的属性注入是在 initializeBean() 的时候处理的,即 populateBean() 之后,由 ConfigurationPropertiesBindingPostProcessor 处理的,最终会委托给 Environment 来处理(参看:SpringBoot 配置项解析)。
@Value 的属性注入是在 populateBean() 的时候处理的,是当作依赖进行注入的。最后是通过 embeddedValueResolvers(StringValueResoulver) 解析的,它非常强大,支持 占位符 ${} spEL(#{})

StringValueResolver、EmbeddedValueResolver
EmbeddedValueResolver implements StringValueResolver。EmbeddedValueResolver 非常强大,它是 spring 配置解析的核心。先解析占位符 ${},再解析 spEL(#{})

 1 public class EmbeddedValueResolver implements StringValueResolver {
 2     private final BeanExpressionContext exprContext;
 3     private final BeanExpressionResolver exprResolver;
 4 
 5     public EmbeddedValueResolver(ConfigurableBeanFactory beanFactory) {
 6         this.exprContext = new BeanExpressionContext(beanFactory, null);
 7         this.exprResolver = beanFactory.getBeanExpressionResolver(); // 实现类为:StandardBeanExpressionResolver
 8     }
 9 
10     @Override
11     public String resolveStringValue(String strVal) {
12         // 1. 解析占位符${}
13         String value = this.exprContext.getBeanFactory().resolveEmbeddedValue(strVal);
14         if (this.exprResolver != null && value != null) {
15             // 2. 解析 spEL: #{}
16             Object evaluated = this.exprResolver.evaluate(value, this.exprContext);
17             value = (evaluated != null ? evaluated.toString() : null);
18         }
19         return value;
20     }
21 
22 }

配置写法小技巧:
可以使用嵌套写法 和 默认值。举例:
${server.error.path:${error.path:/error}}

问题思考:
在使用 disconf 托管配置文件时,会配置 org.springframework.context.support.PropertySourcesPlaceholderConfigurer 或者 com.baidu.disconf.client.addons.properties.ReloadingPropertyPlaceholderConfigurer,被托管的配置都会纳入 spring 管理。如果是这样的话,我们在使用 SpringBoot @ConfigurationProperties 形式的配置时,是不是就可以不用写 @PropertySource("classpath:redis.properties") 来指定配置文件了,这样该多方便啊。那确实可以这么干吗?

分析:
通过测试发现是不可以的,因为 @ConfigurationProperties 最终委托给 Environment 来处理,而 PropertySourcesPlaceholderConfigurer 和 ReloadingPropertyPlaceholderConfigurer 都不受 Environment 控制,所以是不支持的。
而 @Value 却是可以注入 disconf 托管的配置的,因为 @Value 注入的配置会通过 StringValueResoulver 来解析,而 PropertySourcesPlaceholderConfigurer 和 ReloadingPropertyPlaceholderConfigurer 管理的配置,最终会间接通过 StringValueResolver 来解析

猜你喜欢

转载自www.cnblogs.com/kevin-yuan/p/12213644.html