You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
source-code-hunter/docs/Spring/clazz/Spring-PropertySources.md

15 KiB

Spring PropertySources

MutablePropertySources

  • 全路径: org.springframework.core.env.MutablePropertySources

  • MutablePropertySources类内部存储了List<PropertySource<?>>对象,主要是针对List<PropertySource<?>> 进行的操作.换句话说就是对 list 操作的实现

  • 类注解如下

public class MutablePropertySources implements PropertySources {

   private final List<PropertySource<?>> propertySourceList = new CopyOnWriteArrayList<>();


   /**
    * Create a new {@link MutablePropertySources} object.
    *
    * 构造方法
    */
   public MutablePropertySources() {
   }

   /**
    * Create a new {@code MutablePropertySources} from the given propertySources
    * object, preserving the original order of contained {@code PropertySource} objects.
    * 构造方法, 传递一个集合, 将集合中的数据放入 {@code propertySourceList}.
    */
   public MutablePropertySources(PropertySources propertySources) {
      this();
      // PropertySources 是一个迭代器接口的实现,通过循环取出信息放入到 propertySourceList 中
      for (PropertySource<?> propertySource : propertySources) {
         // 放入方法
         addLast(propertySource);
      }
   }


   /**
    * 获取迭代器对象
    */
   @Override
   public Iterator<PropertySource<?>> iterator() {
      return this.propertySourceList.iterator();
   }

   /**
    * 获取 Spliterator 对象
    */
   @Override
   public Spliterator<PropertySource<?>> spliterator() {
      return Spliterators.spliterator(this.propertySourceList, 0);
   }

   /**
    * 获取流
    */
   @Override
   public Stream<PropertySource<?>> stream() {
      return this.propertySourceList.stream();
   }

   /**
    * 判断是否存在 name
    * @param name the {@linkplain PropertySource#getName() name of the property source} to find
    */
   @Override
   public boolean contains(String name) {
      return this.propertySourceList.contains(PropertySource.named(name));
   }

   /**
    * 获取 PropertySource 信息
    * @param name the {@linkplain PropertySource#getName() name of the property source} to find
    * @return
    */
   @Override
   @Nullable
   public PropertySource<?> get(String name) {
      // 获取 name 所在的索引位置
      int index = this.propertySourceList.indexOf(PropertySource.named(name));
      // get方法获取结果
      return (index != -1 ? this.propertySourceList.get(index) : null);
   }


   /**
    * Add the given property source object with highest precedence.
    *
    * 头插数据
    */
   public void addFirst(PropertySource<?> propertySource) {
      removeIfPresent(propertySource);
      this.propertySourceList.add(0, propertySource);
   }

   /**
    * Add the given property source object with lowest precedence.
    *
    * 尾插数据
    */
   public void addLast(PropertySource<?> propertySource) {
      removeIfPresent(propertySource);
      this.propertySourceList.add(propertySource);
   }

   /**
    * Add the given property source object with precedence immediately higher
    * than the named relative property source.
    *
    * 在relativePropertySourceName的索引位置前添加数据
    */
   public void addBefore(String relativePropertySourceName, PropertySource<?> propertySource) {
      assertLegalRelativeAddition(relativePropertySourceName, propertySource);
      removeIfPresent(propertySource);
      int index = assertPresentAndGetIndex(relativePropertySourceName);
      addAtIndex(index, propertySource);
   }

   /**
    * Add the given property source object with precedence immediately lower
    * than the named relative property source.
    * 在relativePropertySourceName的索引位置后添加数据
    */
   public void addAfter(String relativePropertySourceName, PropertySource<?> propertySource) {
      assertLegalRelativeAddition(relativePropertySourceName, propertySource);
      // 删除存在的数据
      removeIfPresent(propertySource);
      // 获取所有
      int index = assertPresentAndGetIndex(relativePropertySourceName);
      // 在索引+1出添加数据
      addAtIndex(index + 1, propertySource);
   }

   /**
    * Return the precedence of the given property source, {@code -1} if not found.
    * 获取索引位置
    */
   public int precedenceOf(PropertySource<?> propertySource) {
      return this.propertySourceList.indexOf(propertySource);
   }

   /**
    * Remove and return the property source with the given name, {@code null} if not found.
    * 删除索引位置
    * @param name the name of the property source to find and remove
    */
   @Nullable
   public PropertySource<?> remove(String name) {
      // 获取索引
      int index = this.propertySourceList.indexOf(PropertySource.named(name));
      // 删除索引上的数据
      return (index != -1 ? this.propertySourceList.remove(index) : null);
   }

   /**
    * Replace the property source with the given name with the given property source object.
    * 替换 name 的信息
    * @param name the name of the property source to find and replace
    * @param propertySource the replacement property source
    * @throws IllegalArgumentException if no property source with the given name is present
    * @see #contains
    */
   public void replace(String name, PropertySource<?> propertySource) {
      // 获取索引位置
      int index = assertPresentAndGetIndex(name);
      // 设置具体所应位置的值
      this.propertySourceList.set(index, propertySource);
   }

   /**
    * Return the number of {@link PropertySource} objects contained.
    * 数量
    */
   public int size() {
      return this.propertySourceList.size();
   }

   @Override
   public String toString() {
      return this.propertySourceList.toString();
   }

   /**
    * Ensure that the given property source is not being added relative to itself.
    * 确保两个 PropertySource 的 name不相同
    */
   protected void assertLegalRelativeAddition(String relativePropertySourceName, PropertySource<?> propertySource) {
      // 获取 PropertySource 的名字
      String newPropertySourceName = propertySource.getName();
      // 历史名字和新的名字是否相同
      if (relativePropertySourceName.equals(newPropertySourceName)) {
         throw new IllegalArgumentException(
               "PropertySource named '" + newPropertySourceName + "' cannot be added relative to itself");
      }
   }

   /**
    * Remove the given property source if it is present.
    * 删除已存在的数据
    */
   protected void removeIfPresent(PropertySource<?> propertySource) {
      this.propertySourceList.remove(propertySource);
   }

   /**
    * Add the given property source at a particular index in the list.
    * 指定索引位置插入数据
    */
   private void addAtIndex(int index, PropertySource<?> propertySource) {
      removeIfPresent(propertySource);
      this.propertySourceList.add(index, propertySource);
   }

   /**
    * Assert that the named property source is present and return its index.
    * 获取 name 所在的索引位置
    * @param name {@linkplain PropertySource#getName() name of the property source} to find
    * @throws IllegalArgumentException if the named property source is not present
    */
   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;
   }

}

PropertySources

  • 类路径: org.springframework.core.env.PropertySources

  • 详细说明如下

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.
    * 判断是否存在 name
    * @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.
    * 获取 PropertySource
    * @param name the {@linkplain PropertySource#getName() name of the property source} to find
    */
   @Nullable
   PropertySource<?> get(String name);

}

PropertySource

  • 类路径: org.springframework.core.env.PropertySource

  • 存有两个子类

    1. StubPropertySource
    2. ComparisonPropertySource 3. 调用getSourcecontainsPropertygetProperty 都会直接异常
public abstract class PropertySource<T> {

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

	/**
	 * 属性名称
	 */
	protected final String name;

	/**
	 * 值
	 */
	protected final T source;


	/**
	 * Create a new {@code PropertySource} with the given name and source object.
	 */
	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 {@code PropertySource} with the given name and with a new
	 * {@code Object} instance as the underlying source.
	 * <p>Often useful in testing scenarios when creating anonymous implementations
	 * that never query an actual source but rather return hard-coded values.
	 */
	@SuppressWarnings("unchecked")
	public PropertySource(String name) {
		this(name, (T) new Object());
	}

	/**
	 * Return a {@code PropertySource} implementation intended for collection comparison purposes only.
	 * <p>Primarily for internal use, but given a collection of {@code PropertySource} objects, may be
	 * used as follows:
	 * <pre class="code">
	 * {@code List<PropertySource<?>> sources = new ArrayList<PropertySource<?>>();
	 * sources.add(new MapPropertySource("sourceA", mapA));
	 * sources.add(new MapPropertySource("sourceB", mapB));
	 * assert sources.contains(PropertySource.named("sourceA"));
	 * assert sources.contains(PropertySource.named("sourceB"));
	 * assert !sources.contains(PropertySource.named("sourceC"));
	 * }</pre>
	 * The returned {@code PropertySource} will throw {@code UnsupportedOperationException}
	 * if any methods other than {@code equals(Object)}, {@code hashCode()}, and {@code toString()}
	 * are called.
	 * @param name the name of the comparison {@code PropertySource} to be created and returned.
	 */
	public static PropertySource<?> named(String name) {
		return new ComparisonPropertySource(name);
	}

	/**
	 * Return the name of this {@code PropertySource}.
	 */
	public String getName() {
		return this.name;
	}

	/**
	 * Return the underlying source object for this {@code PropertySource}.
	 */
	public T getSource() {
		return this.source;
	}

	/**
	 * Return whether this {@code PropertySource} contains the given name.
	 * <p>This implementation simply checks for a {@code null} return value
	 * from {@link #getProperty(String)}. Subclasses may wish to implement
	 * a more efficient algorithm if possible.
	 * @param name the property name to find
	 */
	public boolean containsProperty(String name) {
		// getProperty 抽象方法子类实现
		return (getProperty(name) != null);
	}

	/**
	 * Return the value associated with the given name,
	 * or {@code null} if not found.
	 * // getProperty 抽象方法子类实现
	 * @param name the property to find
	 * @see PropertyResolver#getRequiredProperty(String)
	 */
	@Nullable
	public abstract Object getProperty(String name);

	/**
	 * This {@code PropertySource} object is equal to the given object if:
	 * <ul>
	 * <li>they are the same instance
	 * <li>the {@code name} properties for both objects are equal
	 * </ul>
	 * <p>No properties other than {@code name} are evaluated.
	 */
	@Override
	public boolean equals(@Nullable Object other) {
		return (this == other || (other instanceof PropertySource &&
				ObjectUtils.nullSafeEquals(this.name, ((PropertySource<?>) other).name)));
	}

	/**
	 * Return a hash code derived from the {@code name} property
	 * of this {@code PropertySource} object.
	 */
	@Override
	public int hashCode() {
		return ObjectUtils.nullSafeHashCode(this.name);
	}

	/**
	 * Produce concise output (type and name) if the current log level does not include
	 * debug. If debug is enabled, produce verbose output including the hash code of the
	 * PropertySource instance and every name/value property pair.
	 * <p>This variable verbosity is useful as a property source such as system properties
	 * or environment variables may contain an arbitrary number of property pairs,
	 * potentially leading to difficult to read exception and log messages.
	 * @see Log#isDebugEnabled()
	 */
	@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 + "'}";
		}
	}

	/**
	 * {@code PropertySource} to be used as a placeholder in cases where an actual
	 * property source cannot be eagerly initialized at application context
	 * creation time.  For example, a {@code ServletContext}-based property source
	 * must wait until the {@code ServletContext} object is available to its enclosing
	 * {@code ApplicationContext}.  In such cases, a stub should be used to hold the
	 * intended default position/order of the property source, then be replaced
	 * during context refresh.
	 * @see org.springframework.context.support.AbstractApplicationContext#initPropertySources()
	 * @see org.springframework.web.context.support.StandardServletEnvironment
	 * @see org.springframework.web.context.support.ServletContextPropertySource
	 */
	public static class StubPropertySource extends PropertySource<Object> {

		public StubPropertySource(String name) {
			super(name, new Object());
		}

		/**
		 * Always returns {@code null}.
		 */
		@Override
		@Nullable
		public String getProperty(String name) {
			return null;
		}
	}


	/**
	 * A {@code PropertySource} implementation intended for collection comparison
	 * purposes.
	 *
	 * @see PropertySource#named(String)
	 */
	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);
		}
	}

}

类图

PropertySource.png