@Value
提供自动注入值的功能:
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Value {
String value();
}
其中,value可输入${}
和#{}
:
${}
: 配置文件、Environment variables、Program arguments、VM options等
#{}
: SpEL表达式
@Value
由AutowiredAnnotationBeanPostProcessor
提供解析处理,AutowiredAnnotationBeanPostProcessor
是创世的几个Bean之一,其加入Bean容器步骤如下:
// 支持解析@Autowired @Value 以及JSR-330的@Inject
public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor,
MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
....
}
该类是一个BeanPostProcessor
,对每一个Bean的初始化过程定义了很多了钩子做处理。
处理步骤及顺序是:
MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
:扫描类中使用@Autowired
和@Value
的元素,包括字段(静态字段不行)、构造函数、setter,扫描结果放入Map<String, InjectionMetadata> injectionMetadataCache
。SmartInstantiationAwareBeanPostProcessor#postProcessProperties
:从injectionMetadataCache
获取注解的元素,实施注入过程,其中对@Value
传入的${}
和#{}
进行解析。
以字段注解@Value
为例:
最后走到了InjectionMetadata#inject -> AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject -> AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#resolveFieldValue -> DefaultListableBeanFactory#resolveDependency -> DefaultListableBeanFactory#doResolveDependency
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
...
@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
if (value instanceof String) {
// 解析${} 由PropertySourcePlaceHolderConfigurer$$Lambda解析
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (beanName != null && containsBean(beanName) ?
getMergedBeanDefinition(beanName) : null);
// 解析#{}, 使用BeanExpressionResolver
value = evaluateBeanDefinitionString(strVal, bd);
}
}
...
}
此外,org.springframework.beans.factory.config.PlaceholderConfigurerSupport
也能提供解析${}
和#{}
的能力,默认解析${}
,可以继承该类自定义解析字符和解析方式。