Spring @value源码分析

一、@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();
	}

4.获取配置文件中占位符对应值详细过程

// 从配置文件中获取占位符的值 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);
				}
			}
		}
	}

propertySources结构从图中可以看出,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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值