ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Spring属性源PropertySource

2021-09-15 18:29:51  阅读:160  来源: 互联网

标签:PropertySource return String Spring source 属性 public name


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

MutablePropertySourcesPropertySources的基础上,增加了可变性集合操作

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;
    }
}

标签:PropertySource,return,String,Spring,source,属性,public,name
来源: https://blog.csdn.net/ystyaoshengting/article/details/120314356

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有