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中的配置有效,注意不要用系统的参数名相同