Spring属性源抽象PropertySource

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/andy_zhang2007/article/details/84302620

概述

对于各种基于"名称/值"对(key/value pair)的属性源,Spring将其抽象成了抽象泛型类PropertySource<T>。底层的属性源T可以是容纳属性信息的任意类型,比如java.util.Properties,java.util.Map,ServletContext,ServletConfig对象,或者是命令行参数CommandLineArgs对象。类PropertySource的方法getSource()用于获取底层的属性源对象T。顶层的属性源对象经过PropertySource封装,从而具有统一的访问方式。

以下是该抽象类的常用的一些具体实现类:

实现类 说明
RandomValuePropertySource 封装一个random对象为属性源,用于获取int,long,uuid随机数
MapPropertySource 封装一个Map<String,Object>对象为属性源
ServletConfigPropertySource 封装一个ServletConfig对象为属性源
ServletContextPropertySource 封装一个ServletContext对象为属性源
SystemEnvironmentPropertySource 继承自MapPropertySource
StandardEnvironment用于将System.getenv()封装成一个属性源
在获取属性的属性名上针对不同环境做了处理,比如getProperty("foo.bar")会匹配"foo.bar",“foo_bar”,“FOO.BAR"或者"FOO_BAR”,如果想获取的属性名称中含有-,会被当作_处理。
SimpleCommandLinePropertySource 将命令行参数字符串数组转换成一个CommandLineArgs对象,然后封装成一个属性源
比如一个springboot应用SpringApplication启动时,如果提供了命令行参数,他们就会被封装成一个SimpleCommandLinePropertySource对象放到上下文环境中去。
PropertiesPropertySource 继承自MapPropertySource,将一个java.util.Properties对象封装为属性源

它们之间的继承关系如下:
PropertySource及其实现类

注意这里的EnumerablePropertySource抽象类,它为PropertySource增加了一个String[] getPropertyNames()方法,要求实现类提供,从而使相应的属性源对象可以被列举访问所包含的各个属性值对。

源码分析

// 仅分析核心抽象
package org.springframework.core.env;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;

/**
 * Abstract base class representing a source of name/value property pairs. The underlying
 * #getSource() source object may be of any type T that encapsulates
 * properties. Examples include java.util.Properties objects, java.util.Map
 * objects, ServletContext and ServletConfig objects (for access to init
 * parameters). Explore the PropertySource type hierarchy to see provided
 * implementations.
 * 
 * 抽象基类,用于表示一个名称/值属性对的来源,简称为属性源。底层的属性源对象的类型通过泛型类T指定。
 *
 * PropertySource objects are not typically used in isolation, but rather
 * through a PropertySources object, which aggregates property sources and in
 * conjunction with a PropertyResolver implementation that can perform
 * precedence-based searches across the set of PropertySources.
 *
 * PropertySource 对象通常并不孤立使用,而是将多个PropertySource对象封装成一个PropertySources
 * 对象来使用。另外还会有一个PropertyResolver属性解析器工作在PropertySources对象上,基于特定的优先级,
 * 来访问这些属性源对象中的属性。
 * 
 * PropertySource identity is determined not based on the content of
 * encapsulated properties, but rather based on the #getName() name of the
 * PropertySource alone. This is useful for manipulating PropertySource
 * objects when in collection contexts. See operations in MutablePropertySources
 * as well as the #named(String) and #toString() methods for details.
 * PropertySource有一个唯一标识id,这个唯一标识id不是基于所封装的属性内容,而是基于指定给
 * 这个PropertySource对象的名称属性#getName()。
 *
 * Note that when working with
 * org.springframework.context.annotation.Configuration Configuration classes that
 * the @org.springframework.context.annotation.PropertySource PropertySource
 * annotation provides a convenient and declarative way of adding property sources to the
 * enclosing Environment.
 *
 * @author Chris Beams
 * @since 3.1
 * @param <T> the source type
 * @see PropertySources
 * @see PropertyResolver
 * @see PropertySourcesPropertyResolver
 * @see MutablePropertySources
 * @see org.springframework.context.annotation.PropertySource
 */
public abstract class PropertySource<T> {

	protected final Log logger = LogFactory.getLog(getClass());

	protected final String name;

	protected final T source;


	/**
	 * Create a new PropertySource with the given name and source object.
	 * 将某个T类型的底层属性源source对象封装成一个特定名称为name的PropertySource对象
	 */
	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;
	}

	/**
	 * Create a new PropertySource with the given name and with a new
	 * Object instance as the underlying source.
	 * Often useful in testing scenarios when creating anonymous implementations
	 * that never query an actual source but rather return hard-coded values.
	 * 使用一个空对象构建一个指定名称为name的PropertySource对象。通常用于测试目的。
	 */
	@SuppressWarnings("unchecked")
	public PropertySource(String name) {
		this(name, (T) new Object());
	}


	/**
	 * Return the name of this PropertySource.获取属性源名称
	 */
	public String getName() {
		return this.name;
	}

	/**
	 * Return the underlying source object for this PropertySource.
	 * 获取所封装的底层属性源对象,类型为泛型T。
	 */
	public T getSource() {
		return this.source;
	}

	/**
	 * Return whether this PropertySource contains the given name.
	 * This implementation simply checks for a null return value
	 * from #getProperty(String). Subclasses may wish to implement
	 * a more efficient algorithm if possible.
	 * 查看指定名称为name的属性是否被当前PropertySource对象包含,
	 * 判断方法:尝试获取该名称的属性值,如果值不为null认为是包含;否则认为是不包含。
	 * 继承类可以提供不同的判断方法和实现。
	 * @param name the property name to find
	 */
	public boolean containsProperty(String name) {
		return (getProperty(name) != null);
	}

	/**
	 * Return the value associated with the given name,
	 * or null if not found.
	 * 获取指定名称为name的属性的值,如果该属性不存在于该PropertySource对象,返回null
	 * @param name the property to find
	 * @see PropertyResolver#getRequiredProperty(String)
	 */
	@Nullable
	public abstract Object getProperty(String name);



}

猜你喜欢

转载自blog.csdn.net/andy_zhang2007/article/details/84302620