Spring屬性源抽象PropertySource
阿新 • • 發佈:2018-12-03
概述
對於各種基於"名稱/值"對(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 物件封裝為屬性源 |
它們之間的繼承關係如下:
注意這裡的
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);
}