Spring 工具:PropertySourcesPropertyResolver 从PropertySources中解析属性

概述

Spring框架将某个属性源抽象成了类PropertySource,又将多个属性源PropertySource组合抽象为接口PropertySources。对某个PropertySource对象中属性的解析,抽象成了接口PropertyResolver,而类PropertySourcesPropertyResolver则是Spring用于解析一个PropertySources对象中属性的工具类。Spring应用Environment对象中对其PropertySources对象的属性解析,就是通过这样一个对象。

// Spring Environment 实现类的抽象基类 AbstractEnvironment代码片段
private final ConfigurablePropertyResolver propertyResolver =
			new PropertySourcesPropertyResolver(this.propertySources);

源码解析

package org.springframework.core.env;

import org.springframework.lang.Nullable;

/**
 * PropertyResolver implementation that resolves property values against
 * an underlying set of PropertySources.
 * 一个PropertyResolver实现类,用于解析一个PropertySources对象中的属性源集合中的属性。
 * 
 * 这里PropertySourcesPropertyResolver继承自基类AbstractPropertyResolver,
 * AbstractPropertyResolver提供了很多方法实现,不过这里不做过多解析,而仅仅关注
 * 如何获取一个属性的值的逻辑。
 * 
 * @author Chris Beams
 * @author Juergen Hoeller
 * @since 3.1
 * @see PropertySource
 * @see PropertySources
 * @see AbstractEnvironment
 */
public class PropertySourcesPropertyResolver extends AbstractPropertyResolver {
	// PropertySources形式存在的属性源集合,该工具的工作对象
	@Nullable
	private final PropertySources propertySources;


	/**
	 * Create a new resolver against the given property sources.
	 * @param propertySources the set of PropertySource objects to use
	 */
	public PropertySourcesPropertyResolver(@Nullable PropertySources propertySources) {
		this.propertySources = propertySources;
	}

	// 查看是否包含某个指定名称的属性,判断方法:
	// 1. 底层任何一个属性源包含该属性的话就认为是包含;
	// 2. 否则认为是不包含。
	@Override
	public boolean containsProperty(String key) {
		if (this.propertySources != null) {
			for (PropertySource<?> propertySource : this.propertySources) {
				if (propertySource.containsProperty(key)) {
					return true;
				}
			}
		}
		return false;
	}

	// 获取某个指定名称的属性的值,如果该属性不被包含的话,返回null
	// 不管该属性的值是什么类型,将它转换成字符串类型
	@Override
	@Nullable
	public String getProperty(String key) {
		return getProperty(key, String.class, true);
	}

	// 获取某个指定名称的属性的值,并将其转换成指定的类型,如果该属性不被包含的话,返回null
	@Override
	@Nullable
	public <T> T getProperty(String key, Class<T> targetValueType) {
		return getProperty(key, targetValueType, true);
	}
	
	// 获取某个指定名称的属性的值,如果该属性不被包含的话,返回null
	// 不管该属性的值是什么类型,将它转换成字符串类型
	@Override
	@Nullable
	protected String getPropertyAsRawString(String key) {
		return getProperty(key, String.class, false);
	}
	// 获取某个指定名称的属性的值,并将其转换成指定的类型,如果该属性不被包含的话,返回null
	// resolveNestedPlaceholders参数指示是否要解析属性值中包含的占位符
	@Nullable
	protected <T> T getProperty(String key, Class<T> targetValueType, boolean resolveNestedPlaceholders) {
		if (this.propertySources != null) {
			// 遍历每个属性源,如果发现目标属性被某个属性源包含,则获取它的值并按要求做相应的处理然后返回处理
			// 后的值从这里使用for循环的方式来看,可以将属性源看作是一个List,索引较小的属性源先被访问,也就
			// 是说,索引较小的属性源具有较高优先级
			for (PropertySource<?> propertySource : this.propertySources) {
				if (logger.isTraceEnabled()) {
					logger.trace("Searching for key '" + key + "' in PropertySource '" +
							propertySource.getName() + "'");
				}
				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);
				}
			}
		}
		if (logger.isTraceEnabled()) {
			logger.trace("Could not find key '" + key + "' in any property source");
		}
		// 任何属性源中都不包含该属性,返回null
		return null;
	}

	/**
	 * Log the given key as found in the given PropertySource, resulting in
	 * the given value.
	 * The default implementation writes a debug log message with key and source.
	 * As of 4.3.3, this does not log the value anymore in order to avoid accidental
	 * logging of sensitive settings. Subclasses may override this method to change
	 * the log level and/or log message, including the property's value if desired.
	 * @param key the key found
	 * @param propertySource the PropertySource that the key has been found in
	 * @param value the corresponding value
	 * @since 4.3.1
	 */
	protected void logKeyFound(String key, PropertySource<?> propertySource, Object value) {
		if (logger.isDebugEnabled()) {
			logger.debug("Found key '" + key + "' in PropertySource '" + propertySource.getName() +
					"' with value of type " + value.getClass().getSimpleName());
		}
	}

}

参考文章

Spring 工具建模:PropertyResolver 属性解析工具基本功能建模

你可能感兴趣的:(spring,Spring,Core,Spring,内部工具)