PropertySource
PropertySource
主要是对属性源的抽象,包含属性源名称和属性源内容对象。其方法主要是对这两个字段进行操作。
public abstract class PropertySource<T> {
//属性源名称
protected final String name;
//属性源
protected final T source;
// 构造器
public PropertySource(String name, T source) {
Assert.hasText(name, "Property source name must contain at least one character");
Assert.notNull(source, "Property source must not be null");
this.name = name;
this.source = source;
}
//不带source的构造器
@SuppressWarnings("unchecked")
public PropertySource(String name) {
this(name, (T) new Object());
}
//获取name字段
public String getName() {
return this.name;
}
//获取source字段
public T getSource() {
return this.source;
}
//是否包含属性
public boolean containsProperty(String name) {
return (getProperty(name) != null);
}
//获取属性值
@Nullable
public abstract Object getProperty(String name);
//两个属性源对象是否相同,仅比较名称
@Override
public boolean equals(@Nullable Object other) {
return (this == other || (other instanceof PropertySource &&
ObjectUtils.nullSafeEquals(this.name, ((PropertySource<?>) other).name)));
}
//根据名称生成hash码
@Override
public int hashCode() {
return ObjectUtils.nullSafeHashCode(this.name);
}
//重写的toString方法
@Override
public String toString() {
if (logger.isDebugEnabled()) {
return getClass().getSimpleName() + "@" + System.identityHashCode(this) +
" {name='" + this.name + "', properties=" + this.source + "}";
}
else {
return getClass().getSimpleName() + " {name='" + this.name + "'}";
}
}
//生成一个仅比较的属性源对象,不可用来获取name和source
public static PropertySource<?> named(String name) {
return new ComparisonPropertySource(name);
}
//占位属性源
//这是一个只有名称标识,没有任何值的属性源,只用作占位符,当实际的属性源对象不能在ApplicationContext应用上下文创建的时候被立即初始化,则会使用它来占位,以保证属性源集合的搜索顺序
//当初始化时再用实际属性源替换掉(根据name匹配)占位对象
public static class StubPropertySource extends PropertySource<Object> {
public StubPropertySource(String name) {
super(name, new Object());
}
@Override
@Nullable
public String getProperty(String name) {
return null;
}
}
//可比较的属性源类,仅用作根据名称进行比较的场景
static class ComparisonPropertySource extends StubPropertySource {
private static final String USAGE_ERROR =
"ComparisonPropertySource instances are for use with collection comparison only";
public ComparisonPropertySource(String name) {
super(name);
}
@Override
public Object getSource() {
throw new UnsupportedOperationException(USAGE_ERROR);
}
@Override
public boolean containsProperty(String name) {
throw new UnsupportedOperationException(USAGE_ERROR);
}
@Override
@Nullable
public String getProperty(String name) {
throw new UnsupportedOperationException(USAGE_ERROR);
}
}
}
EnumerablePropertySource
可枚举属性的属性源,额外定义了获取所有属性名称的方法
public abstract class EnumerablePropertySource<T> extends PropertySource<T> {
public EnumerablePropertySource(String name, T source) {
super(name, source);
}
protected EnumerablePropertySource(String name) {
super(name);
}
//属性名称是否存在
@Override
public boolean containsProperty(String name) {
return ObjectUtils.containsElement(getPropertyNames(), name);
}
//获取所有的属性名称
public abstract String[] getPropertyNames();
}
MapPropertySource
public class MapPropertySource extends EnumerablePropertySource<Map<String, Object>> {
// source为Map对象
public MapPropertySource(String name, Map<String, Object> source) {
super(name, source);
}
// 在Map对象中获取指定name对应的值
@Override
@Nullable
public Object getProperty(String name) {
return this.source.get(name);
}
// 是否包含某属性,重写了`EnumerablePropertySource`的此方法,目的是为了提升查询的效率
@Override
public boolean containsProperty(String name) {
return this.source.containsKey(name);
}
// 获取熟悉名称数组
@Override
public String[] getPropertyNames() {
return StringUtils.toStringArray(this.source.keySet());
}
}
PropertiesPropertySource
// 和`MapPropertySource`没太大区别,唯一的操作就是对source进行了加锁,从而避免并发场景下的线程不安全因素。
public class PropertiesPropertySource extends MapPropertySource {
@SuppressWarnings({"rawtypes", "unchecked"})
public PropertiesPropertySource(String name, Properties source) {
super(name, (Map) source);
}
protected PropertiesPropertySource(String name, Map<String, Object> source) {
super(name, source);
}
@Override
public String[] getPropertyNames() {
synchronized (this.source) {
return super.getPropertyNames();
}
}
}
SystemEnvironmentPropertySource
系统环境属性源,此属性源在根据name获取对应的value时,与父类实现不太一样。它认为name不区分大小写,且name中包含的’.‘点与’_'下划线是等效的,因此在获取value之前,都会对name进行一次处理。
public class SystemEnvironmentPropertySource extends MapPropertySource {
public SystemEnvironmentPropertySource(String name, Map<String, Object> source) {
super(name, source);
}
public boolean containsProperty(String name) {
return this.getProperty(name) != null;
}
@Nullable
public Object getProperty(String name) {
String actualName = this.resolvePropertyName(name);
if (this.logger.isDebugEnabled() && !name.equals(actualName)) {
this.logger.debug("PropertySource '" + this.getName() + "' does not contain property '" + name + "', but found equivalent '" + actualName + "'");
}
return super.getProperty(actualName);
}
protected final String resolvePropertyName(String name) {
Assert.notNull(name, "Property name must not be null");
String resolvedName = this.checkPropertyName(name);
if (resolvedName != null) {
return resolvedName;
} else {
String uppercasedName = name.toUpperCase();
if (!name.equals(uppercasedName)) {
resolvedName = this.checkPropertyName(uppercasedName);
if (resolvedName != null) {
return resolvedName;
}
}
return name;
}
}
@Nullable
private String checkPropertyName(String name) {
if (this.containsKey(name)) {
return name;
} else {
String noDotName = name.replace('.', '_');
if (!name.equals(noDotName) && this.containsKey(noDotName)) {
return noDotName;
} else {
String noHyphenName = name.replace('-', '_');
if (!name.equals(noHyphenName) && this.containsKey(noHyphenName)) {
return noHyphenName;
} else {
String noDotNoHyphenName = noDotName.replace('-', '_');
return !noDotName.equals(noDotNoHyphenName) && this.containsKey(noDotNoHyphenName) ? noDotNoHyphenName : null;
}
}
}
}
private boolean containsKey(String name) {
return this.isSecurityManagerPresent() ? ((Map)this.source).keySet().contains(name) : ((Map)this.source).containsKey(name);
}
protected boolean isSecurityManagerPresent() {
return System.getSecurityManager() != null;
}
}
CommandLinePropertySource
public abstract class CommandLinePropertySource<T> extends EnumerablePropertySource<T> {
public static final String COMMAND_LINE_PROPERTY_SOURCE_NAME = "commandLineArgs";
public static final String DEFAULT_NON_OPTION_ARGS_PROPERTY_NAME = "nonOptionArgs";
private String nonOptionArgsPropertyName = "nonOptionArgs";
public CommandLinePropertySource(T source) {
super("commandLineArgs", source);
}
public CommandLinePropertySource(String name, T source) {
super(name, source);
}
public void setNonOptionArgsPropertyName(String nonOptionArgsPropertyName) {
this.nonOptionArgsPropertyName = nonOptionArgsPropertyName;
}
public final boolean containsProperty(String name) {
if (this.nonOptionArgsPropertyName.equals(name)) {
return !this.getNonOptionArgs().isEmpty();
} else {
return this.containsOption(name);
}
}
@Nullable
public final String getProperty(String name) {
List optionValues;
if (this.nonOptionArgsPropertyName.equals(name)) {
optionValues = this.getNonOptionArgs();
return optionValues.isEmpty() ? null : StringUtils.collectionToCommaDelimitedString(optionValues);
} else {
optionValues = this.getOptionValues(name);
return optionValues == null ? null : StringUtils.collectionToCommaDelimitedString(optionValues);
}
}
protected abstract boolean containsOption(String var1);
@Nullable
protected abstract List<String> getOptionValues(String var1);
protected abstract List<String> getNonOptionArgs();
}
SimpleCommandLinePropertySource
public class SimpleCommandLinePropertySource extends CommandLinePropertySource<CommandLineArgs> {
public SimpleCommandLinePropertySource(String... args) {
super((new SimpleCommandLineArgsParser()).parse(args));
}
public SimpleCommandLinePropertySource(String name, String[] args) {
super(name, (new SimpleCommandLineArgsParser()).parse(args));
}
public String[] getPropertyNames() {
return StringUtils.toStringArray(((CommandLineArgs)this.source).getOptionNames());
}
protected boolean containsOption(String name) {
return ((CommandLineArgs)this.source).containsOption(name);
}
@Nullable
protected List<String> getOptionValues(String name) {
return ((CommandLineArgs)this.source).getOptionValues(name);
}
protected List<String> getNonOptionArgs() {
return ((CommandLineArgs)this.source).getNonOptionArgs();
}
}
PropertySources
PropertySources
是对属性源列表操作的封装。主要加入了迭代器
、可变性
和集合操作
。这个类有一个唯一的子类,即:MutablePropertySources
。
// 在迭代器的基础上,增加了判断属性源是否存在,以及根据属性源名称获取属性源的操作。
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);
}
MutablePropertySources
MutablePropertySources
在PropertySources
的基础上,增加了可变性
和集合操作
。
public class MutablePropertySources implements PropertySources {
// 使用`CopyOnWriteArrayList`,保持集合操作的线程安全性。
private final List<PropertySource<?>> propertySourceList = new CopyOnWriteArrayList<>();
//构造空集合
public MutablePropertySources() {}
//构造指定集合
public MutablePropertySources(PropertySources propertySources) {
this();
for (PropertySource<?> propertySource : propertySources) {
addLast(propertySource);
}
}
// ******
// 以下所有方法都是集合操作,主要包括:
// 增、删、改、查、替换、断言存在性等操作
// 非常简单
// ******
@Override
public Iterator<PropertySource<?>> iterator() {
return this.propertySourceList.iterator();
}
@Override
public Spliterator<PropertySource<?>> spliterator() {
return Spliterators.spliterator(this.propertySourceList, 0);
}
@Override
public Stream<PropertySource<?>> stream() {
return this.propertySourceList.stream();
}
@Override
public boolean contains(String name) {
return this.propertySourceList.contains(PropertySource.named(name));
}
@Override
@Nullable
public PropertySource<?> get(String name) {
int index = this.propertySourceList.indexOf(PropertySource.named(name));
return (index != -1 ? this.propertySourceList.get(index) : null);
}
//添加propertySource到集合头部,优先级最高
public void addFirst(PropertySource<?> propertySource) {
removeIfPresent(propertySource);
this.propertySourceList.add(0, propertySource);
}
//添加propertySource到集合尾部,优先级最低
public void addLast(PropertySource<?> propertySource) {
removeIfPresent(propertySource);
this.propertySourceList.add(propertySource);
}
//添加给定的属性源对象,其优先级高于指定的相关属性源
public void addBefore(String relativePropertySourceName, PropertySource<?> propertySource) {
assertLegalRelativeAddition(relativePropertySourceName, propertySource);
removeIfPresent(propertySource);
int index = assertPresentAndGetIndex(relativePropertySourceName);
addAtIndex(index, propertySource);
}
//添加给定的属性源对象,其优先级低于指定的相关属性源
public void addAfter(String relativePropertySourceName, PropertySource<?> propertySource) {
assertLegalRelativeAddition(relativePropertySourceName, propertySource);
removeIfPresent(propertySource);
int index = assertPresentAndGetIndex(relativePropertySourceName);
addAtIndex(index + 1, propertySource);
}
//返回给定属性源的优先级,如果没有找到,则返回-1
public int precedenceOf(PropertySource<?> propertySource) {
return this.propertySourceList.indexOf(propertySource);
}
//根据属性源名称,移除指定的属性源
@Nullable
public PropertySource<?> remove(String name) {
int index = this.propertySourceList.indexOf(PropertySource.named(name));
return (index != -1 ? this.propertySourceList.remove(index) : null);
}
//用新的属性源对象替换掉指定的属性源名称对应的属性源对象
public void replace(String name, PropertySource<?> propertySource) {
int index = assertPresentAndGetIndex(name);
this.propertySourceList.set(index, propertySource);
}
//返回属性源集合的大小
public int size() {
return this.propertySourceList.size();
}
@Override
public String toString() {
return this.propertySourceList.toString();
}
//确保指定的属性源不是相对于自身添加,也就是说不能添加属性源到自己的前面或后面
protected void assertLegalRelativeAddition(String relativePropertySourceName, PropertySource<?> propertySource) {
String newPropertySourceName = propertySource.getName();
if (relativePropertySourceName.equals(newPropertySourceName)) {
throw new IllegalArgumentException(
"PropertySource named '" + newPropertySourceName + "' cannot be added relative to itself");
}
}
//移除指定的属性源
protected void removeIfPresent(PropertySource<?> propertySource) {
this.propertySourceList.remove(propertySource);
}
//在指定的下标添加属性源
private void addAtIndex(int index, PropertySource<?> propertySource) {
removeIfPresent(propertySource);
this.propertySourceList.add(index, propertySource);
}
//断言给定的名称所对应的属性源存在,并且返回其下标
private int assertPresentAndGetIndex(String name) {
int index = this.propertySourceList.indexOf(PropertySource.named(name));
if (index == -1) {
throw new IllegalArgumentException("PropertySource named '" + name + "' does not exist");
}
return index;
}
}