Spring学习之@Value
文章目录
注解说明
@Value 是Spring提供用于处理属性与表达式注入的注解,可标注在字段、方法或构造器的参数上,并且支持动态解析SpringMVC中的方法参数。支持注入方式:
- 直接注入如: @Value(“test”)
- ${my.app.myProp} 属性注入
- #{systemProperties.myProp} SpEL表达式
它提供了不同的配置源(属性文件、系统属性)的注入
注解属性
@Value 注解只有一个属性 value
,表示要注入的实际值的表达式,支持属性与SpEL表达式两种方式
测试代码
以下测试代码MyController的username的注入值为: tomyli,而不是配置文件中的admin
|
|
application.properties配置文件
|
|
源码阅读
@Value
注解的处理由 AutowiredAnnotationBeanPostProcessor
类负责,与处理 @Autowired 注解的类为同一个PostProcessor。主要的处理逻辑实现在 DefaultListableBeanFactory#doResolveDependency
方法,对于 @Value注解的处理主要集中在第2步,解析@Value的操作主要分为3步

整体调用图
解析配置的value属性值
首先会调用 QualifierAnnotationAutowireCandidateResolver#getSuggestedValue
来确认属性 value
的值,确认逻辑由 findValue()
方法执行,此方法会查询 @Value 注解并解析出配置的属性 value 值

查找解析值
解析到配置的属性value后,判断其为 String 类型,则调用 resolveEmbeddedValue()
方法对配置的表达式进行解析,在此方法中会循环遍历 embeddedValueResolvers 来调用 resolver的 resolveStringValue()
来解析值,这个String的解析操作会交给 AbstractEnvironment#resolvePlaceholders
方法,进而委托给 AbstractPropertyResolver#resolvePlaceholders
方法来解析具体的值配置信息,而获取配置的具体值的操作发生在 PropertySourcesPropertyResolver#getProperty
, 在此方法中会循环遍历 propertySources,propertySources 中持有多个 propertySource,依次对每个 propertySource 调用 getProperty()
来查询值,找到一个满足条件的值后就返直接返回了,此时 propertySource 的顺序决定了查找资源的顺序


由图可知,查找的顺序为: systemProperties->systemEnvironment->application.properties
。调试发现在 systemEnvironment中查找到了 USER 的值 tomyli
,找到后就返回,不会再查 application.properties
文件中配置的 USER 的值了
AbstractEnvironment实现了PropertyResolver接口
解析嵌入的值,实际上就是替换占位符的工作
Resolver在什么时候设置的?
在 finishBeanFactoryInitialization
阶段,Spring会判断当前beanFactory是否存在值解析Resolver,没有则进行添加,而此时添加Resolver的解析就是 AbstractEnvironment类的resolvePlaceholders方法
StringValueResolver 被标识为 @FunctionalInterface
propertySources是在哪设置的?
systemProperties 和 systemEnvironment 是在 StandardEnvironment#customizePropertySources
添加的
- systemProperties系统变量主要包含Java系统相关信息(版本、VM信息)和系统相关信息(操作系统版本名称架构、文件分隔符等)和用户信息组成
- systemEnvironment系统环境变量主要为当前运行系统的信息,包含shell、用户登录名、PATH等变量信息
application.properties 文件配置是在 PropertySourceProcessor#processPropertySource
方法通过调用 addPropertySource() 时添加的
转换值为必要的类型
查找到值会调用 TypeConverterSupport#convertIfNecessary
来对获取的值进行类型转换,此方法会委托 TypeConverterDelegate类的convertIfNecessary 方法来进行真正的类型转换,在此方法会对常见的Java标准类型(数组、集合、Map、String、Number)与期望的类型进行比较,匹配上进行相应类型的转换

总结
@Value注解是Spring提供的用户注入属性的注解,其主要处理类为 AutowiredAnnotationPostProcessor
,解析操作分为3步:
- 解析属性value值
- 查找配置的属性值对应的真实值
- 找到后进行相应的类型转换
在配置要注入的值时需要关注 @Value 注解属性配置的查找顺序,Spring会先查询 systemProperties和systemEnvironment 中的配置,匹配到就返回,想要让配置在application.properties中的配置有效,注意不要用系统的参数名相同