一、@value赋值流程
1.获取实例化对象上的@value、@Autowired等注解
2.解析占位符
3.解析占位符详细过程(去除${}符号)
4.获取配置文件中占位符对应值详细过程
二、加载外部配置文件
前言
对Spring源码的分析,以SpringBoot项目为例开展
创建测试类:
@Component
public class FindValueTest {
@Value("${server.port}")
private String port;
}
application.properties设置属性配置
server.port=8080
spring.application.name=spring-functions
一、@value赋值流程
1.获取实例化对象上的@value、@Autowired等注解
@value的处理是从Bean对象实例化后开始的,因此从main方法的SpringApplication.run()
一直点进去,
//实例化所有非懒加载的单例
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
=========================================================
getBean(beanName);
=================
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
........
........
if (instanceWrapper == null) {
//创建实例对象
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
...........
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
// 收集并RootBeanDefinition上对应的@value/@Autowired注解
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
........
........
try {
//属性赋值
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
........
........
}
注解的解析获取是在applyMergedBeanDefinitionPostProcessors方法里
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
// 遍历所有MergedBeanDefinitionPostProcessor的实现类,
// 其中包括AutowiredAnnotationBeanPostProcessor,解析@value和@Autowired注解
if (bp instanceof MergedBeanDefinitionPostProcessor) {
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
// 执行 postProcessMergedBeanDefinition方法
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
}
====================================================
AutowiredAnnotationBeanPostProcessor postProcessMergedBeanDefinition的实现
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
=====================================
随后的方法调用 findAutowiringMetadata --> buildAutowiringMetadata
buildAutowiringMetadata方法中,重要部分:
ReflectionUtils.doWithLocalFields(targetClass, field -> {
// 获取@value/@Autowired注解
AnnotationAttributes ann = findAutowiredAnnotation(field);
if (ann != null) {
// 静态变量不赋值
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static fields: " + field);
}
return;
}
boolean required = determineRequiredStatus(ann);
currElements.add(new AutowiredFieldElement(field, required));
}
});
=======================
private AnnotationAttributes findAutowiredAnnotation(AccessibleObject ao) {
if (ao.getAnnotations().length > 0) {
// autowiring annotations have to be local
// 遍历this.autowiredAnnotationTypes(包含了@value/@Autowired)集合,匹配对象上的注解。autowiredAnnotationTypes是在AutowiredAnnotationBeanPostProcessor构造器中赋值的。
for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ao, type);
if (attributes != null) {
return attributes;
}
}
}
return null;
}
==========================
最后将获取到的注解放到injectionMetadataCache对象中
private final Map<String, InjectionMetadata> injectionMetadataCache = new ConcurrentHashMap<>(256);
获取@value/@Autowired过程结束。
2.解析占位符
// 从populateBean方法开始
populateBean(beanName, mbd, instanceWrapper);
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
............
............
for (BeanPostProcessor bp : getBeanPostProcessors()) {
//遍历BeanPostProcessor,找到InstantiationAwareBeanPostProcessor子类
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// AutowiredAnnotationBeanPostProcessor 类是实现类之一,postProcessProperties方法解析并赋值@value对应的占位符
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
........
// 已弃用
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
}
}
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
// AutowiredAnnotationBeanPostProcessor 类的实现
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
// 从injectionMetadataCache 缓存中获取bean的@value属性
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
// 通过反射给对象赋值
metadata.inject(bean, beanName, pvs);
}
...................
...................
return pvs;
}
AutowiredAnnotationBeanPostProcessor 的内部类AutowiredFieldElement实现inject方法:
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Field field = (Field) this.member;
Object value;
...........
...........
TypeConverter typeConverter = beanFactory.getTypeConverter();
try {
// 从资源文件中获取${port}对应的值
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
.................
if (value != null) {
ReflectionUtils.makeAccessible(field);
// 通过反射设置值
field.set(bean, value);
}
}
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
...............
...............
// 获取属性对应的占位符${server.port}
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
if (value != null) {
if (value instanceof String) {
// 从配置文件中获取占位符${server.port}的值
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (beanName != null && containsBean(beanName) ?
getMergedBeanDefinition(beanName) : null);
// 将占位符替换成配置文件中的值
value = evaluateBeanDefinitionString(strVal, bd);
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
}
}
..................
Object result = instanceCandidate;
return result;
}
}
3.解析占位符${server.port} --> server.port详细过程
获取属性对应的占位符${server.port}
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
=====================================================
// 解析${server.port} --> server.port
String strVal = resolveEmbeddedValue((String) value);
=====================================================
@Nullable
public String resolveEmbeddedValue(@Nullable String value) {
.................
String result = value;
for (StringValueResolver resolver : this.embeddedValueResolvers) {
// 解析${server.port} --> server.port
result = resolver.resolveStringValue(result);
.................
}
return result;
}
this.embeddedValueResolvers是一个PropertySourcesPlaceholderConfigurer的lambda表达式。
protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess,
final ConfigurablePropertyResolver propertyResolver) throws BeansException {
propertyResolver.setPlaceholderPrefix(this.placeholderPrefix);
propertyResolver.setPlaceholderSuffix(this.placeholderSuffix);
propertyResolver.setValueSeparator(this.valueSeparator);
// lambda表达式会触发这里的执行
StringValueResolver valueResolver = strVal -> {
String resolved = (this.ignoreUnresolvablePlaceholders ?
propertyResolver.resolvePlaceholders(strVal) :
propertyResolver.resolveRequiredPlaceholders(strVal));
if (this.trimValues) {
resolved = resolved.trim();
}
return (resolved.equals(this.nullValue) ? null : resolved);
};
//PropertySourcesPlaceholderConfigurer会注入一个PropertySourcesPropertyResolver解析器
//依次会调用propertyResolver.resolveRequiredPlaceholders(strVal));--> doResolvePlaceholders(text, this.strictHelper); --> helper.replacePlaceholders(text, this::getPropertyAsRawString);--> parseStringValue(value, placeholderResolver, null);
protected String parseStringValue(
String value, PlaceholderResolver placeholderResolver, @Nullable Set<String> visitedPlaceholders) {
// 解析${server.port} --> server.port
int startIndex = value.indexOf(this.placeholderPrefix);
if (startIndex == -1) {
return value;
}
StringBuilder result = new StringBuilder(value);
while (startIndex != -1) {
int endIndex = findPlaceholderEndIndex(result, startIndex);
if (endIndex != -1) {
String placeholder = result.substring(startIndex + this.placeholderPrefix.length(), endIndex);
String originalPlaceholder = placeholder;
if (visitedPlaceholders == null) {
visitedPlaceholders = new HashSet<>(4);
}
if (!visitedPlaceholders.add(originalPlaceholder)) {
throw new IllegalArgumentException(
"Circular placeholder reference '" + originalPlaceholder + "' in property definitions");
}
// Recursive invocation, parsing placeholders contained in the placeholder key.
// 递归parseStringValue方法 为了解决${${server.port}}多个$的情况
placeholder = parseStringValue(placeholder, placeholderResolver, visitedPlaceholders);
// Now obtain the value for the fully resolved key...
// 从配置文件中获取占位符对应的值 8080
String propVal = placeholderResolver.resolvePlaceholder(placeholder);
.....................
return result.toString();
}
// 从配置文件中获取占位符的值 8080
String propVal = placeholderResolver.resolvePlaceholder(placeholder);
=====================
PropertySourcesPropertyResolver resolvePlaceholder方法的实现:
protected String getPropertyAsRawString(String key) {
return getProperty(key, String.class, false);
}
=====================
protected <T> T getProperty(String key, Class<T> targetValueType, boolean resolveNestedPlaceholders) {
if (this.propertySources != null) {
// 配置文件解析后,数据都存放在this.propertySources里面
for (PropertySource<?> propertySource : this.propertySources) {
.............
// 从propertySource中获取server.port对应的值8080
Object value = propertySource.getProperty(key);
if (value != null) {
if (resolveNestedPlaceholders && value instanceof String) {
value = resolveNestedPlaceholders((String) value);
}
logKeyFound(key, propertySource, value);
return convertValueIfNecessary(value, targetValueType);
}
}
}
}
从图中可以看出,OriginTrackedMapPropertySource来自classpath:/application.properties文件。
二、加载外部配置文件
Spring可以通过XML或者@PropertySource指定外部配置文件
// 从SpringApplication.run()方法的prepareEnvironment方法开始
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
===============================
private ConfigurableEnvironment prepareEnvironment(
SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments) {
// Create and configure the environment
// 创建Environment,加载spring配置文件
ConfigurableEnvironment environment = getOrCreateEnvironment();
configureEnvironment(environment, applicationArguments.getSourceArgs());
listeners.environmentPrepared(environment);
bindToSpringApplication(environment);
if (!this.isCustomEnvironment) {
environment = new EnvironmentConverter(getClassLoader())
.convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());
}
ConfigurationPropertySources.attach(environment);
return environment;
}
private ConfigurableEnvironment getOrCreateEnvironment() {
if (this.environment != null) {
return this.environment;
}
switch (this.webApplicationType) {
case SERVLET:
// 会创建一个StandardServletEnvironment的环境
return new StandardServletEnvironment();
case REACTIVE:
return new StandardReactiveWebEnvironment();
default:
return new StandardEnvironment();
}
}
从StandardServletEnvironment类的继承关系可以看到,extends AbstractEnvironment,再看AbstractEnvironment 无参构造方法
public AbstractEnvironment() {
// 调用了customizePropertySources方法,子类也会调用对应的重写方法customizePropertySources
customizePropertySources(this.propertySources);
}
==================================
Environment会添加以下4个配置文件:
propertySources.addLast(new StubPropertySource("servletConfigInitParams"));
propertySources.addLast(new StubPropertySource("servletContextInitParams"));
propertySources.addLast(new MapPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));
propertySources.addLast(new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
// 然后是SpringBoot加载配置文件
listeners.environmentPrepared(environment);
// 通过listen监听加载classpath:/,classpath:/config/,file:./,file:./config/,file:./config/*/ 目录下的properties或yml文件
参考文章:
https://blog.csdn.net/qq_35971258/article/details/128287580
https://www.zhihu.com/tardis/sogou/art/438556340