org.springframework.core.env.PropertySource/PropertySources/PropertyResolver

  针对PropertySource/PropertySources/PropertyResolver这三个类的理解,是理解SpringBoot环境上下文Environment的基础。

  1.PropertySource是SpringBoot中处理配置信息(键值对)的顶层抽象,是一个抽象类。在逻辑上提供name属性和source属性,默认name用于唯一标识一个(复写equals方法,name相等即返回true)配置源,source属性是是一个泛型对象,主要的功能方法是public abstract Object getProperty(String name),该抽象的设计思路是当PropertySource的实现类含有不同类型的source时,source对象负责完成抽象方法getProperty的逻辑,返回的是Object对象。

  2.PropertySources(PropertySources extends Iterable<PropertySource<?>>)是一个接口,是多个PropertySource的使用规范,其设计思路是一般配置源具有多个,配置信息的存储是以PropertySource集合的方式存储,即PropertySources对象。MutablePropertySources是PropertySources的唯一实现类,持有一个空的PropertySource泛型的列表,并提供操作列表元素的各种方法,并未直接对外提供getProperty的方法(这个正是提供PropertyResolver接口的原因)。

  3.PropertyResolver是一个接口,该接口提供了比PropertySource更丰富的获取属性的API。

package org.springframework.core.env;
import org.springframework.lang.Nullable;
public interface PropertyResolver {
	boolean containsProperty(String key);
	String getProperty(String key);
	String getProperty(String key, String defaultValue);
	<T> T getProperty(String key, Class<T> targetType);
	<T> T getProperty(String key, Class<T> targetType, T defaultValue);
	String getRequiredProperty(String key) throws IllegalStateException;
	<T> T getRequiredProperty(String key, Class<T> targetType) throws IllegalStateException;
	String resolvePlaceholders(String text);
	String resolveRequiredPlaceholders(String text) throws IllegalArgumentException;

}

  至此,PropertySource/PropertySources/PropertyResolver三个类的设计原理就显而易见了,PropertyResolver接口的实现类持有PropertySources对象(PropertySource集合),PropertyResolver使用PropertySource集合中的PropertySource元素的getProperty方法实现其各种跟配置信息有关的抽象方法。

  补充:

  1.StubPropertySource extends PropertySource<Object>是PropertySource的空实现,一般用于占位,getProperty方法总是返回null,前文已经讲过当存在多个PropertySource时是以列表的形式存储在PropertySources对象中,在创建PropertySources对象时,如果需要先初始化列表中的PropertySource对象,可以先使用StubPropertySource对象进行占位。使用场景:如ServletContext的配置信息必须得等到ApplicationContext加载完毕才能得到,可以在初始化PropertySources中的各种配置源时,先将代表ServletContext的配置源的PropertySource添加到PropertySources的列表中(配置源具有优先级,顺序具有意义),等到得到ServletContext的配置信息再替换代表列表中占位的PropertySource(替换的逻辑,前文已经介绍,name属性唯一标识配置源,根据PropertySource的name属性进行替换)。

  2.ComparisonPropertySource extends StubPropertySource代表的是一个含有name属性的PropertySource,仅能调用getName方法,调用其他的方法将会报错。该实现类的作用就是比较的作用。使用场景:

  

//创建一个PropertySource列表并添加两个元素
List<PropertySource<?>> sources = new ArrayList<PropertySource<?>>();
sources.add(new MapPropertySource("sourceA", mapA));
sources.add(new MapPropertySource("sourceB", mapB));
//判断sources集合中是否含有指定的PropertySource
//PropertySource.named("sourceA")返回一个name属性为sourceA的ComparisonPropertySource 
//contains方法的逻辑可以查看ArrayList.contains源码,除了null的考虑外,使用的就是equals方法
//而PropertySource的equals的实现比较的就是其name属性

assert sources.contains(PropertySource.named("sourceA"));

 

posted @ 2022-11-03 23:03  wuyiping  阅读(303)  评论(0编辑  收藏  举报