参考文章:
Spring 的环境解析由,数据源,解析器,剖面,环境组合
Properties的解析器
PropertyResolver属性解析器,用于解析任何基础源的属性的接口
解析器顶级接口
public interface PropertyResolver {
// 是否包含某个属性
boolean containsProperty(String key);
// 获取属性值 如果找不到返回null
@Nullable
String getProperty(String key);
// 获取属性值,如果找不到返回默认值
String getProperty(String key, String defaultValue);
// 获取指定类型的属性值,找不到返回null
@Nullable
<T> T getProperty(String key, Class<T> targetType);
// 获取指定类型的属性值,找不到返回默认值
<T> T getProperty(String key, Class<T> targetType, T defaultValue);
// 获取属性值,找不到抛出异常IllegalStateException
String getRequiredProperty(String key) throws IllegalStateException;
// 获取指定类型的属性值,找不到抛出异常IllegalStateException
<T> T getRequiredProperty(String key, Class<T> targetType) throws IllegalStateException;
// 替换文本中的占位符(${key})到属性值,找不到不解析
String resolvePlaceholders(String text);
// 替换文本中的占位符(${key})到属性值,找不到抛出异常IllegalArgumentException
String resolveRequiredPlaceholders(String text) throws IllegalArgumentException;
}
其子类包含:
- ConfigurablePropertyResolver:供属性类型转换的功能
- AbstractPropertyResolver:解析属性文件的抽象基类
- PropertySourcesPropertyResolver:PropertyResolver 的实现者,他对一组 PropertySources 提供属性解析服务
ConfigurablePropertyResolver
public interface ConfigurablePropertyResolver extends PropertyResolver {
// 返回执行类型转换时使用的 ConfigurableConversionService
ConfigurableConversionService getConversionService();
// 设置 ConfigurableConversionService
void setConversionService(ConfigurableConversionService conversionService);
// 设置占位符前缀
void setPlaceholderPrefix(String placeholderPrefix);
// 设置占位符后缀
void setPlaceholderSuffix(String placeholderSuffix);
// 设置占位符与默认值之间的分隔符
void setValueSeparator(@Nullable String valueSeparator);
// 设置当遇到嵌套在给定属性值内的不可解析的占位符时是否抛出异常
// 当属性值包含不可解析的占位符时,getProperty(String)及其变体的实现必须检查此处设置的值以确定正确的行为。
void setIgnoreUnresolvableNestedPlaceholders(boolean ignoreUnresolvableNestedPlaceholders);
// 指定必须存在哪些属性,以便由validateRequiredProperties()验证
void setRequiredProperties(String... requiredProperties);
// 验证setRequiredProperties指定的每个属性是否存在并解析为非null值
void validateRequiredProperties() throws MissingRequiredPropertiesException;
}
其实现类
AbstractPropertyResolver 作为基类它仅仅只是设置了一些解析属性文件所需要配置或者转换器
PropertySourcesPropertyResolver是其真正的实现类
其内部维持一个数据源集合对象
@Nullable
private final PropertySources propertySources;
public interface PropertySources extends Iterable<PropertySource<?>> {
/**
* Return a sequential {@link Stream} containing the property sources.
* @since 5.1
*/
default Stream<PropertySource<?>> stream() {
return StreamSupport.stream(spliterator(), false);
}
/**
* Return whether a property source with the given name is contained.
* @param name the {@linkplain PropertySource#getName() name of the property source} to find
*/
boolean contains(String name);
/**
* Return the property source with the given name, {@code null} if not found.
* @param name the {@linkplain PropertySource#getName() name of the property source} to find
*/
@Nullable
PropertySource<?> get(String name);
}
其主要的值获取操作
protected <T> T getProperty(String key, Class<T> targetValueType, boolean resolveNestedPlaceholders) {
if (this.propertySources != null) {
// 遍历 propertySources 数组
for (PropertySource<?> propertySource : this.propertySources) {
if (logger.isTraceEnabled()) {
logger.trace("Searching for key '" + key + "' in PropertySource '" +
propertySource.getName() + "'");
}
// 获得 key 对应的 value 值
Object value = propertySource.getProperty(key);
if (value != null) {
// 如果解决嵌套占位符,解析占位符
if (resolveNestedPlaceholders && value instanceof String) {
value = resolveNestedPlaceholders((String) value);
}
// 如果未找到 key 对应的值,则打印日志
logKeyFound(key, propertySource, value);
// value 的类型转换
return convertValueIfNecessary(value, targetValueType);
}
}
}
if (logger.isTraceEnabled()) {
logger.trace("Could not find key '" + key + "' in any property source");
}
return null;
}
主要的几个逻辑;
占位符解析
value = resolveNestedPlaceholders((String) value);
protected String resolveNestedPlaceholders(String value) {
return (this.ignoreUnresolvableNestedPlaceholders ?
resolvePlaceholders(value) : resolveRequiredPlaceholders(value));
}
类型转换
convertValueIfNecessary(value, targetValueType)
protected <T> T convertValueIfNecessary(Object value, @Nullable Class<T> targetType) {
if (targetType == null) {
return (T) value;
}
ConversionService conversionServiceToUse = this.conversionService;
if (conversionServiceToUse == null) {
// Avoid initialization of shared DefaultConversionService if
// no standard type conversion is needed in the first place...
if (ClassUtils.isAssignableValue(targetType, value)) {
return (T) value;
}
conversionServiceToUse = DefaultConversionService.getSharedInstance();
}
return conversionServiceToUse.convert(value, targetType);
}
Environment
表示当前应用程序正在运行的环境;两个关键方面:profile 和 properties。 Environment 对象的作用,是确定哪些配置文件(如果有)当前处于活动状态,以及默认情况下哪些配置文件(如果有)应处于活动状态
其顶级接口
public interface Environment extends PropertyResolver {
/**
* 返回此环境下**的配置文件集
*/
String[] getActiveProfiles();
/**
* 如果未设置**配置文件,则返回默认的**的配置文件集
*/
String[] getDefaultProfiles();
/**
*/
@Deprecated
boolean acceptsProfiles(String... profiles);
/**
*/
boolean acceptsProfiles(Profiles profiles);
}
其类的体系结构
- PropertyResolver:提供属性访问功能
- Environment:提供访问和判断 profiles 的功能
- ConfigurableEnvironment:提供设置**的 profile 和默认的 profile 的功能以及操作 Properties 的工具
- ConfigurableWebEnvironment:提供配置 Servlet 上下文和 Servlet 参数的功能
- AbstractEnvironment:实现了 ConfigurableEnvironment 接口,默认属性和存储容器的定义,并且实现了 ConfigurableEnvironment 的方法,并且为子类预留可覆盖了扩展方法
- StandardEnvironment:继承自 AbstractEnvironment ,非 Servlet(Web) 环境下的标准 Environment 实现
- StandardServletEnvironment:继承自 StandardEnvironment ,Servlet(Web) 环境下的标准 Environment 实现
子类ConfigurableEnvironment
提供设置**的 profile 和默认的 profile 的功能以及操作 Properties 的工具
public interface ConfigurableEnvironment extends Environment, ConfigurablePropertyResolver {
// 指定该环境下的 profile 集
void setActiveProfiles(String... profiles);
// 增加此环境的 profile
void addActiveProfile(String profile);
// 设置默认的 profile
void setDefaultProfiles(String... profiles);
// 返回此环境的 PropertySources
MutablePropertySources getPropertySources();
// 尝试返回 System.getenv() 的值,若失败则返回通过 System.getenv(string) 的来访问各个键的映射
Map<String, Object> getSystemEnvironment();
// 尝试返回 System.getProperties() 的值,若失败则返回通过 System.getProperties(string) 的来访问各个键的映射
Map<String, Object> getSystemProperties();
void merge(ConfigurableEnvironment parent);
}
抽象类AbstractEnvironment
提供了基础的实现
有两对变量,这两对变量维护着**和默认配置 profile
private final Set<String> activeProfiles = new LinkedHashSet<>();
private final Set<String> defaultProfiles = new LinkedHashSet<>(getReservedDefaultProfiles());
设置活动的配置
@Override
public void setActiveProfiles(String... profiles) {
Assert.notNull(profiles, "Profile array must not be null");
if (logger.isDebugEnabled()) {
logger.debug("Activating profiles " + Arrays.asList(profiles));
}
synchronized (this.activeProfiles) {
// 清空 activeProfiles
this.activeProfiles.clear();
// 遍历 profiles 数组,添加到 activeProfiles 中
for (String profile : profiles) {
// 校验
validateProfile(profile);
this.activeProfiles.add(profile);
}
}
}
获取 activeProfiles
@Override
public String[] getActiveProfiles() {
return StringUtils.toStringArray(doGetActiveProfiles());
}
protected Set<String> doGetActiveProfiles() {
synchronized (this.activeProfiles) {
// 如果 activeProfiles 为空,则进行初始化
if (this.activeProfiles.isEmpty()) {
// 获得 ACTIVE_PROFILES_PROPERTY_NAME 对应的 profiles 属性值
String profiles = getProperty(ACTIVE_PROFILES_PROPERTY_NAME);
if (StringUtils.hasText(profiles)) {
// 设置到 activeProfiles 中
setActiveProfiles(StringUtils.commaDelimitedListToStringArray(
StringUtils.trimAllWhitespace(profiles)));
}
}
return this.activeProfiles;
}
}