From bdfafcad7ef49bcf4d6fc2f6edde47c9b265ec81 Mon Sep 17 00:00:00 2001 From: huifer Date: Sat, 10 Oct 2020 15:05:33 +0800 Subject: [PATCH] doc: PropertySource --- .../Spring-CommandLinePropertySource.md | 127 +++++++++ .../Spring-ComparisonPropertySource.md | 44 ++++ .../Spring-CompositePropertySource.md | 105 ++++++++ .../Spring-EnumerablePropertySource.md | 46 ++++ .../Spring-MapPropertySource.md | 43 ++++ .../Spring-MockPropertySource.md | 112 ++++++++ .../Spring-PropertiesPropertySource.md | 35 +++ .../Spring-ResourcePropertySource.md | 241 ++++++++++++++++++ .../Spring-ServletConfigPropertySource.md | 36 +++ .../Spring-ServletContextPropertySource.md | 37 +++ .../Spring-SimpleCommandLineArgsParser.md | 55 ++++ .../Spring-SimpleCommandLinePropertySource.md | 175 +++++++++++++ .../Spring-StubPropertySource.md | 28 ++ 13 files changed, 1084 insertions(+) create mode 100644 docs/Spring/clazz/PropertySource/Spring-CommandLinePropertySource.md create mode 100644 docs/Spring/clazz/PropertySource/Spring-ComparisonPropertySource.md create mode 100644 docs/Spring/clazz/PropertySource/Spring-CompositePropertySource.md create mode 100644 docs/Spring/clazz/PropertySource/Spring-EnumerablePropertySource.md create mode 100644 docs/Spring/clazz/PropertySource/Spring-MapPropertySource.md create mode 100644 docs/Spring/clazz/PropertySource/Spring-MockPropertySource.md create mode 100644 docs/Spring/clazz/PropertySource/Spring-PropertiesPropertySource.md create mode 100644 docs/Spring/clazz/PropertySource/Spring-ResourcePropertySource.md create mode 100644 docs/Spring/clazz/PropertySource/Spring-ServletConfigPropertySource.md create mode 100644 docs/Spring/clazz/PropertySource/Spring-ServletContextPropertySource.md create mode 100644 docs/Spring/clazz/PropertySource/Spring-SimpleCommandLineArgsParser.md create mode 100644 docs/Spring/clazz/PropertySource/Spring-SimpleCommandLinePropertySource.md create mode 100644 docs/Spring/clazz/PropertySource/Spring-StubPropertySource.md diff --git a/docs/Spring/clazz/PropertySource/Spring-CommandLinePropertySource.md b/docs/Spring/clazz/PropertySource/Spring-CommandLinePropertySource.md new file mode 100644 index 0000000..ee6e22b --- /dev/null +++ b/docs/Spring/clazz/PropertySource/Spring-CommandLinePropertySource.md @@ -0,0 +1,127 @@ +# Spring CommandLinePropertySource + +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [SourceHot-spring](https://github.com/SourceHot/spring-framework-read) + + +- 类全路径: `org.springframework.core.env.CommandLinePropertySource` +- 作用: 用来存储命令行参数 + + + + + +```java +public abstract class CommandLinePropertySource extends EnumerablePropertySource { + + public static final String COMMAND_LINE_PROPERTY_SOURCE_NAME = "commandLineArgs"; + + public static final String DEFAULT_NON_OPTION_ARGS_PROPERTY_NAME = "nonOptionArgs"; + + + private String nonOptionArgsPropertyName = DEFAULT_NON_OPTION_ARGS_PROPERTY_NAME; + + + + public CommandLinePropertySource(T source) { + // 命令行参数, 属性值 + super(COMMAND_LINE_PROPERTY_SOURCE_NAME, source); + } + + public CommandLinePropertySource(String name, T source) { + // 参数名称, 参数值 + super(name, source); + } + + + public void setNonOptionArgsPropertyName(String nonOptionArgsPropertyName) { + this.nonOptionArgsPropertyName = nonOptionArgsPropertyName; + } + + @Override + public final boolean containsProperty(String name) { + // 输入值是否等于nonOptionArgs + if (this.nonOptionArgsPropertyName.equals(name)) { + // 等于后判断参数列表是否为空 + return !this.getNonOptionArgs().isEmpty(); + } + // 是否存在 name 属性 + return this.containsOption(name); + } + + @Override + @Nullable + public final String getProperty(String name) { + if (this.nonOptionArgsPropertyName.equals(name)) { + // 获取 非可选项参数列表 + Collection nonOptionArguments = this.getNonOptionArgs(); + if (nonOptionArguments.isEmpty()) { + return null; + } + else { + // 可选参数命令行参数 + return StringUtils.collectionToCommaDelimitedString(nonOptionArguments); + } + } + Collection optionValues = this.getOptionValues(name); + if (optionValues == null) { + return null; + } + else { + // 命令行参数 + return StringUtils.collectionToCommaDelimitedString(optionValues); + } + } + + + /** + * 是否存在 name 的命令行参数 + */ + protected abstract boolean containsOption(String name); + + /** + * 获取参数列表集合 + */ + @Nullable + protected abstract List getOptionValues(String name); + + /** + * 获取 non-option 参数列表 + */ + protected abstract List getNonOptionArgs(); + +} +``` + + + + + +## getOptionValues + +```java +/** + * Return the collection of values associated with the command line option having the + * given name. + *
    + *
  • if the option is present and has no argument (e.g.: "--foo"), return an empty + * collection ({@code []})
  • + *
  • if the option is present and has a single value (e.g. "--foo=bar"), return a + * collection having one element ({@code ["bar"]})
  • + *
  • if the option is present and the underlying command line parsing library + * supports multiple arguments (e.g. "--foo=bar --foo=baz"), return a collection + * having elements for each value ({@code ["bar", "baz"]})
  • + *
  • if the option is not present, return {@code null}
  • + *
+ * + * 获取参数列表集合 + */ +@Nullable +protected abstract List getOptionValues(String name); +``` + + + +阅读注释可以知道该方法可以获取命令行参数的列表. + +- 如 `--foo`作为开头当输入命令行为 `--foo=bar --foo=baz` 在输入参数名称 `foo` 会得到数据`bar,baz` \ No newline at end of file diff --git a/docs/Spring/clazz/PropertySource/Spring-ComparisonPropertySource.md b/docs/Spring/clazz/PropertySource/Spring-ComparisonPropertySource.md new file mode 100644 index 0000000..832d131 --- /dev/null +++ b/docs/Spring/clazz/PropertySource/Spring-ComparisonPropertySource.md @@ -0,0 +1,44 @@ +# Spring ComparisonPropertySource + +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [SourceHot-spring](https://github.com/SourceHot/spring-framework-read) + + +- 整体代码如下. + - 下面几个调用方法会直接抛出异常 + 1. getSource + 1. containsProperty + 1. getProperty + +```java + 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); + } + } + +``` \ No newline at end of file diff --git a/docs/Spring/clazz/PropertySource/Spring-CompositePropertySource.md b/docs/Spring/clazz/PropertySource/Spring-CompositePropertySource.md new file mode 100644 index 0000000..62eb94a --- /dev/null +++ b/docs/Spring/clazz/PropertySource/Spring-CompositePropertySource.md @@ -0,0 +1,105 @@ +# Spring CompositePropertySource +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [SourceHot-spring](https://github.com/SourceHot/spring-framework-read) + + +- 全路径: `org.springframework.core.env.CompositePropertySource` + +- 整体代码如下 +```java +public class CompositePropertySource extends EnumerablePropertySource { + + /** + * set 集合 + */ + private final Set> propertySources = new LinkedHashSet<>(); + + + /** + * Create a new {@code CompositePropertySource}. + * @param name the name of the property source + */ + public CompositePropertySource(String name) { + super(name); + } + + + @Override + @Nullable + public Object getProperty(String name) { + // 循环 + for (PropertySource propertySource : this.propertySources) { + // 获取存储内容 + Object candidate = propertySource.getProperty(name); + if (candidate != null) { + return candidate; + } + } + return null; + } + + @Override + public boolean containsProperty(String name) { + for (PropertySource propertySource : this.propertySources) { + // 是否存在name + if (propertySource.containsProperty(name)) { + return true; + } + } + return false; + } + + @Override + public String[] getPropertyNames() { + Set names = new LinkedHashSet<>(); + for (PropertySource propertySource : this.propertySources) { + // 类型不同抛出异常 + if (!(propertySource instanceof EnumerablePropertySource)) { + throw new IllegalStateException( + "Failed to enumerate property names due to non-enumerable property source: " + propertySource); + } + // 批量添加 + names.addAll(Arrays.asList(((EnumerablePropertySource) propertySource).getPropertyNames())); + } + // 转换成 array + return StringUtils.toStringArray(names); + } + + + /** + * Add the given {@link PropertySource} to the end of the chain. + * @param propertySource the PropertySource to add + */ + public void addPropertySource(PropertySource propertySource) { + this.propertySources.add(propertySource); + } + + /** + * Add the given {@link PropertySource} to the start of the chain. + * @param propertySource the PropertySource to add + * @since 4.1 + */ + public void addFirstPropertySource(PropertySource propertySource) { + // 头插 + List> existing = new ArrayList<>(this.propertySources); + this.propertySources.clear(); + this.propertySources.add(propertySource); + this.propertySources.addAll(existing); + } + + /** + * Return all property sources that this composite source holds. + * @since 4.1.1 + */ + public Collection> getPropertySources() { + return this.propertySources; + } + + + @Override + public String toString() { + return getClass().getSimpleName() + " {name='" + this.name + "', propertySources=" + this.propertySources + "}"; + } + +} +``` \ No newline at end of file diff --git a/docs/Spring/clazz/PropertySource/Spring-EnumerablePropertySource.md b/docs/Spring/clazz/PropertySource/Spring-EnumerablePropertySource.md new file mode 100644 index 0000000..1a9afec --- /dev/null +++ b/docs/Spring/clazz/PropertySource/Spring-EnumerablePropertySource.md @@ -0,0 +1,46 @@ +# Spring EnumerablePropertySource + +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [SourceHot-spring](https://github.com/SourceHot/spring-framework-read) + +- 全路径: `org.springframework.core.env.EnumerablePropertySource` +- 在这个类中定义了一个抽象方法`getPropertyNames` 用来获取所有的 property 的名称 + +```java + public abstract String[] getPropertyNames(); +``` +- 整体代码如下 +```java +public abstract class EnumerablePropertySource extends PropertySource { + + public EnumerablePropertySource(String name, T source) { + super(name, source); + } + + protected EnumerablePropertySource(String name) { + super(name); + } + + + /** + * Return whether this {@code PropertySource} contains a property with the given name. + *

This implementation checks for the presence of the given name within the + * {@link #getPropertyNames()} array. + * + * 在属性列表中是否存在 properties + * @param name the name of the property to find + */ + @Override + public boolean containsProperty(String name) { + return ObjectUtils.containsElement(getPropertyNames(), name); + } + + /** + * Return the names of all properties contained by the + * 获取所有的 properties 名称 + * {@linkplain #getSource() source} object (never {@code null}). + */ + public abstract String[] getPropertyNames(); + +} +``` \ No newline at end of file diff --git a/docs/Spring/clazz/PropertySource/Spring-MapPropertySource.md b/docs/Spring/clazz/PropertySource/Spring-MapPropertySource.md new file mode 100644 index 0000000..f8db931 --- /dev/null +++ b/docs/Spring/clazz/PropertySource/Spring-MapPropertySource.md @@ -0,0 +1,43 @@ +# Spring MapPropertySource + +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [SourceHot-spring](https://github.com/SourceHot/spring-framework-read) + + +- 类全路径: `org.springframework.core.env.MapPropertySource` +- 内部数据结构是一个`Map` + 这是一个对map的操作. + +- 整体代码如下. + +```java + +public class MapPropertySource extends EnumerablePropertySource> { + + public MapPropertySource(String name, Map source) { + super(name, source); + } + + + @Override + @Nullable + public Object getProperty(String name) { + // 从map中获取 name 对应的value + return this.source.get(name); + } + + @Override + public boolean containsProperty(String name) { + // 判断是否存在 name 属性 + return this.source.containsKey(name); + } + + @Override + public String[] getPropertyNames() { + // 互殴去 map 的所有key + return StringUtils.toStringArray(this.source.keySet()); + } + +} + +``` \ No newline at end of file diff --git a/docs/Spring/clazz/PropertySource/Spring-MockPropertySource.md b/docs/Spring/clazz/PropertySource/Spring-MockPropertySource.md new file mode 100644 index 0000000..4f1ef01 --- /dev/null +++ b/docs/Spring/clazz/PropertySource/Spring-MockPropertySource.md @@ -0,0 +1,112 @@ +# Spring MockPropertySource +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [SourceHot-spring](https://github.com/SourceHot/spring-framework-read) + + +- 内部 source 是 Properties 类型 + + + + + + + +## withProperty + +- 设置属性名称和属性值 + +```java +public MockPropertySource withProperty(String name, Object value) { + this.setProperty(name, value); + return this; +} +``` + + + + + +## setProperty + +```java +public void setProperty(String name, Object value) { + this.source.put(name, value); +} +``` + + + + + +## 完整代码 + + + +```java +public class MockPropertySource extends PropertiesPropertySource { + + /** + * {@value} is the default name for {@link MockPropertySource} instances not + * otherwise given an explicit name. + * @see #MockPropertySource() + * @see #MockPropertySource(String) + */ + public static final String MOCK_PROPERTIES_PROPERTY_SOURCE_NAME = "mockProperties"; + + /** + * Create a new {@code MockPropertySource} named {@value #MOCK_PROPERTIES_PROPERTY_SOURCE_NAME} + * that will maintain its own internal {@link Properties} instance. + */ + public MockPropertySource() { + this(new Properties()); + } + + /** + * Create a new {@code MockPropertySource} with the given name that will + * maintain its own internal {@link Properties} instance. + * @param name the {@linkplain #getName() name} of the property source + */ + public MockPropertySource(String name) { + this(name, new Properties()); + } + + /** + * Create a new {@code MockPropertySource} named {@value #MOCK_PROPERTIES_PROPERTY_SOURCE_NAME} + * and backed by the given {@link Properties} object. + * @param properties the properties to use + */ + public MockPropertySource(Properties properties) { + this(MOCK_PROPERTIES_PROPERTY_SOURCE_NAME, properties); + } + + /** + * Create a new {@code MockPropertySource} with the given name and backed by the given + * {@link Properties} object. + * @param name the {@linkplain #getName() name} of the property source + * @param properties the properties to use + */ + public MockPropertySource(String name, Properties properties) { + super(name, properties); + } + + /** + * Set the given property on the underlying {@link Properties} object. + */ + public void setProperty(String name, Object value) { + // map 操作 + this.source.put(name, value); + } + + /** + * Convenient synonym for {@link #setProperty} that returns the current instance. + * Useful for method chaining and fluent-style use. + * 设置属性名称和属性值 + * @return this {@link MockPropertySource} instance + */ + public MockPropertySource withProperty(String name, Object value) { + this.setProperty(name, value); + return this; + } + +} +``` \ No newline at end of file diff --git a/docs/Spring/clazz/PropertySource/Spring-PropertiesPropertySource.md b/docs/Spring/clazz/PropertySource/Spring-PropertiesPropertySource.md new file mode 100644 index 0000000..967a36e --- /dev/null +++ b/docs/Spring/clazz/PropertySource/Spring-PropertiesPropertySource.md @@ -0,0 +1,35 @@ +# Spring PropertiesPropertySource +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [SourceHot-spring](https://github.com/SourceHot/spring-framework-read) + + +- 全路径: `org.springframework.core.env.PropertiesPropertySource` + + + +- Properties 是map结构。可以做类型转换. +- getPropertyNames 就转换成了父类MapPropertySource的方法了 + - map.keySet() + +```java +public class PropertiesPropertySource extends MapPropertySource { + + @SuppressWarnings({"rawtypes", "unchecked"}) + public PropertiesPropertySource(String name, Properties source) { + super(name, (Map) source); + } + + protected PropertiesPropertySource(String name, Map source) { + super(name, source); + } + + + @Override + public String[] getPropertyNames() { + synchronized (this.source) { + return super.getPropertyNames(); + } + } + +} +``` \ No newline at end of file diff --git a/docs/Spring/clazz/PropertySource/Spring-ResourcePropertySource.md b/docs/Spring/clazz/PropertySource/Spring-ResourcePropertySource.md new file mode 100644 index 0000000..9b29fad --- /dev/null +++ b/docs/Spring/clazz/PropertySource/Spring-ResourcePropertySource.md @@ -0,0 +1,241 @@ +# Spring ResourcePropertySource +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [SourceHot-spring](https://github.com/SourceHot/spring-framework-read) + + +- 全路径: `org.springframework.core.io.support.ResourcePropertySource` + +- source 依然是map结构 + + + + + + + +## getNameForResource + +```java +private static String getNameForResource(Resource resource) { + // 获取 resource 的介绍 + String name = resource.getDescription(); + if (!StringUtils.hasText(name)) { + // 短类名+@+hashcode + name = resource.getClass().getSimpleName() + "@" + System.identityHashCode(resource); + } + return name; +} +``` + + + + + +## withName + +- 创建 ResourcePropertySource 对象, 根据 name 属性 + +```java +public ResourcePropertySource withName(String name) { + if (this.name.equals(name)) { + return this; + } + // Store the original resource name if necessary... + if (this.resourceName != null) { + if (this.resourceName.equals(name)) { + return new ResourcePropertySource(this.resourceName, null, this.source); + } + else { + return new ResourcePropertySource(name, this.resourceName, this.source); + } + } + else { + // Current name is resource name -> preserve it in the extra field... + return new ResourcePropertySource(name, this.name, this.source); + } +} +``` + + + + + +## 构造函数 + +- 通过 location 字符串读取 resource + +```java +public ResourcePropertySource(String name, String location, ClassLoader classLoader) throws IOException { + // 默认资源读取器读取 location 转换成 resource + this(name, new DefaultResourceLoader(classLoader).getResource(location)); +} +``` + + + +- 读取 resource 信息进行存储 + +```java +public ResourcePropertySource(String name, EncodedResource resource) throws IOException { + // 设置 name + map 对象 + // map 对象是 资源信息 + super(name, PropertiesLoaderUtils.loadProperties(resource)); + // 获取 resource name + this.resourceName = getNameForResource(resource.getResource()); +} +``` + + + +## 完整代码 + +```java +public class ResourcePropertySource extends PropertiesPropertySource { + + /** The original resource name, if different from the given name. */ + @Nullable + private final String resourceName; + + + /** + * Create a PropertySource having the given name based on Properties + * loaded from the given encoded resource. + */ + public ResourcePropertySource(String name, EncodedResource resource) throws IOException { + // 设置 name + map 对象 + // map 对象是 资源信息 + super(name, PropertiesLoaderUtils.loadProperties(resource)); + // 获取 resource name + this.resourceName = getNameForResource(resource.getResource()); + } + + /** + * Create a PropertySource based on Properties loaded from the given resource. + * The name of the PropertySource will be generated based on the + * {@link Resource#getDescription() description} of the given resource. + */ + public ResourcePropertySource(EncodedResource resource) throws IOException { + // 设置 key: name, resource 的 name + // 设置 value: resource 资源信息 + super(getNameForResource(resource.getResource()), PropertiesLoaderUtils.loadProperties(resource)); + this.resourceName = null; + } + + /** + * Create a PropertySource having the given name based on Properties + * loaded from the given encoded resource. + */ + public ResourcePropertySource(String name, Resource resource) throws IOException { + super(name, PropertiesLoaderUtils.loadProperties(new EncodedResource(resource))); + this.resourceName = getNameForResource(resource); + } + + /** + * Create a PropertySource based on Properties loaded from the given resource. + * The name of the PropertySource will be generated based on the + * {@link Resource#getDescription() description} of the given resource. + */ + public ResourcePropertySource(Resource resource) throws IOException { + super(getNameForResource(resource), PropertiesLoaderUtils.loadProperties(new EncodedResource(resource))); + this.resourceName = null; + } + + /** + * Create a PropertySource having the given name based on Properties loaded from + * the given resource location and using the given class loader to load the + * resource (assuming it is prefixed with {@code classpath:}). + */ + public ResourcePropertySource(String name, String location, ClassLoader classLoader) throws IOException { + // 默认资源读取器读取 location 转换成 resource + this(name, new DefaultResourceLoader(classLoader).getResource(location)); + } + + /** + * Create a PropertySource based on Properties loaded from the given resource + * location and use the given class loader to load the resource, assuming it is + * prefixed with {@code classpath:}. The name of the PropertySource will be + * generated based on the {@link Resource#getDescription() description} of the + * resource. + */ + public ResourcePropertySource(String location, ClassLoader classLoader) throws IOException { + this(new DefaultResourceLoader(classLoader).getResource(location)); + } + + /** + * Create a PropertySource having the given name based on Properties loaded from + * the given resource location. The default thread context class loader will be + * used to load the resource (assuming the location string is prefixed with + * {@code classpath:}. + */ + public ResourcePropertySource(String name, String location) throws IOException { + this(name, new DefaultResourceLoader().getResource(location)); + } + + /** + * Create a PropertySource based on Properties loaded from the given resource + * location. The name of the PropertySource will be generated based on the + * {@link Resource#getDescription() description} of the resource. + */ + public ResourcePropertySource(String location) throws IOException { + this(new DefaultResourceLoader().getResource(location)); + } + + private ResourcePropertySource(String name, @Nullable String resourceName, Map source) { + super(name, source); + this.resourceName = resourceName; + } + + /** + * Return the description for the given Resource; if the description is + * empty, return the class name of the resource plus its identity hash code. + * @see org.springframework.core.io.Resource#getDescription() + */ + private static String getNameForResource(Resource resource) { + // 获取 resource 的介绍 + String name = resource.getDescription(); + if (!StringUtils.hasText(name)) { + // 短类名+@+hashcode + name = resource.getClass().getSimpleName() + "@" + System.identityHashCode(resource); + } + return name; + } + + /** + * Return a potentially adapted variant of this {@link ResourcePropertySource}, + * overriding the previously given (or derived) name with the specified name. + * @since 4.0.4 + */ + public ResourcePropertySource withName(String name) { + if (this.name.equals(name)) { + return this; + } + // Store the original resource name if necessary... + if (this.resourceName != null) { + if (this.resourceName.equals(name)) { + return new ResourcePropertySource(this.resourceName, null, this.source); + } + else { + return new ResourcePropertySource(name, this.resourceName, this.source); + } + } + else { + // Current name is resource name -> preserve it in the extra field... + return new ResourcePropertySource(name, this.name, this.source); + } + } + + /** + * Return a potentially adapted variant of this {@link ResourcePropertySource}, + * overriding the previously given name (if any) with the original resource name + * (equivalent to the name generated by the name-less constructor variants). + * @since 4.1 + */ + public ResourcePropertySource withResourceName() { + if (this.resourceName == null) { + return this; + } + return new ResourcePropertySource(this.resourceName, null, this.source); + } + +} +``` \ No newline at end of file diff --git a/docs/Spring/clazz/PropertySource/Spring-ServletConfigPropertySource.md b/docs/Spring/clazz/PropertySource/Spring-ServletConfigPropertySource.md new file mode 100644 index 0000000..d832b8b --- /dev/null +++ b/docs/Spring/clazz/PropertySource/Spring-ServletConfigPropertySource.md @@ -0,0 +1,36 @@ +# Spring ServletConfigPropertySource + +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [SourceHot-spring](https://github.com/SourceHot/spring-framework-read) + + +- 类全路径: `org.springframework.web.context.support.ServletConfigPropertySource` +- 内部数据结构是 `ServletConfig` + + +- 整体代码如下 + +```java + +public class ServletConfigPropertySource extends EnumerablePropertySource { + + public ServletConfigPropertySource(String name, ServletConfig servletConfig) { + super(name, servletConfig); + } + + @Override + public String[] getPropertyNames() { + // javax.servlet.ServletConfig.getInitParameterNames + return StringUtils.toStringArray(this.source.getInitParameterNames()); + } + + @Override + @Nullable + public String getProperty(String name) { + // javax.servlet.ServletConfig.getInitParameter + return this.source.getInitParameter(name); + } + +} + +``` \ No newline at end of file diff --git a/docs/Spring/clazz/PropertySource/Spring-ServletContextPropertySource.md b/docs/Spring/clazz/PropertySource/Spring-ServletContextPropertySource.md new file mode 100644 index 0000000..48382ae --- /dev/null +++ b/docs/Spring/clazz/PropertySource/Spring-ServletContextPropertySource.md @@ -0,0 +1,37 @@ +# Spring ServletContextPropertySource + + +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [SourceHot-spring](https://github.com/SourceHot/spring-framework-read) + + +- 类全路径: `org.springframework.web.context.support.ServletContextPropertySource` +- 内部数据结构是 ServletContext 接口 + +- 整体代码如下. + + +```java + +public class ServletContextPropertySource extends EnumerablePropertySource { + + public ServletContextPropertySource(String name, ServletContext servletContext) { + super(name, servletContext); + } + + @Override + public String[] getPropertyNames() { + // javax.servlet.ServletContext.getInitParameterNames 方法调用 + return StringUtils.toStringArray(this.source.getInitParameterNames()); + } + + @Override + @Nullable + public String getProperty(String name) { + // javax.servlet.ServletContext.getInitParameter + return this.source.getInitParameter(name); + } + +} + +``` \ No newline at end of file diff --git a/docs/Spring/clazz/PropertySource/Spring-SimpleCommandLineArgsParser.md b/docs/Spring/clazz/PropertySource/Spring-SimpleCommandLineArgsParser.md new file mode 100644 index 0000000..92f7014 --- /dev/null +++ b/docs/Spring/clazz/PropertySource/Spring-SimpleCommandLineArgsParser.md @@ -0,0 +1,55 @@ +# Spring SimpleCommandLineArgsParser + + +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [SourceHot-spring](https://github.com/SourceHot/spring-framework-read) + + + +- 类全路径: `org.springframework.core.env.SimpleCommandLineArgsParser +- 类作用: 将命令行参数解析成 `org.springframework.core.env.CommandLineArgs` + +- 完整代码如下. +```java + +class SimpleCommandLineArgsParser { + + /** + * Parse the given {@code String} array based on the rules described {@linkplain + * SimpleCommandLineArgsParser above}, returning a fully-populated + * {@link CommandLineArgs} object. + * @param args command line arguments, typically from a {@code main()} method + */ + public CommandLineArgs parse(String... args) { + CommandLineArgs commandLineArgs = new CommandLineArgs(); + for (String arg : args) { + if (arg.startsWith("--")) { + String optionText = arg.substring(2, arg.length()); + String optionName; + String optionValue = null; + if (optionText.contains("=")) { + optionName = optionText.substring(0, optionText.indexOf('=')); + optionValue = optionText.substring(optionText.indexOf('=') + 1, optionText.length()); + } + else { + optionName = optionText; + } + if (optionName.isEmpty() || (optionValue != null && optionValue.isEmpty())) { + throw new IllegalArgumentException("Invalid argument syntax: " + arg); + } + commandLineArgs.addOptionArg(optionName, optionValue); + } + else { + commandLineArgs.addNonOptionArg(arg); + } + } + return commandLineArgs; + } + +} + +``` + +- 处理流程 + 1. 循环命令行参数列表 + 2. 去掉 `--` 和 `=` 获取参数名称和参数值放入结果集合 \ No newline at end of file diff --git a/docs/Spring/clazz/PropertySource/Spring-SimpleCommandLinePropertySource.md b/docs/Spring/clazz/PropertySource/Spring-SimpleCommandLinePropertySource.md new file mode 100644 index 0000000..73af289 --- /dev/null +++ b/docs/Spring/clazz/PropertySource/Spring-SimpleCommandLinePropertySource.md @@ -0,0 +1,175 @@ +# Spring SimpleCommandLinePropertySource + +- 全路径: `org.springframework.core.env.SimpleCommandLinePropertySource` + + + +```java +public class SimpleCommandLinePropertySource extends CommandLinePropertySource {} +``` + +- SimpleCommandLinePropertySource 的source 类型是 CommandLineArgs 具体解释请看下面分析 + + + + + + + +## CommandLineArgs + +两个内部属性 + +```java +class CommandLineArgs { + /** + * 选项参数列表 + */ + private final Map> optionArgs = new HashMap<>(); + + /** + * 非选项参数列表 + */ + private final List nonOptionArgs = new ArrayList<>(); + +} +``` + +### addOptionArg + +添加 选项参数 + +```java +public void addOptionArg(String optionName, @Nullable String optionValue) { + if (!this.optionArgs.containsKey(optionName)) { + this.optionArgs.put(optionName, new ArrayList<>()); + } + if (optionValue != null) { + this.optionArgs.get(optionName).add(optionValue); + } +} +``` + + + +### getOptionNames + +- 获取选项参数列表 + +```java +public Set getOptionNames() { + return Collections.unmodifiableSet(this.optionArgs.keySet()); +} +``` + + + + + +- 其他方法不具体描述了,各位可以查看下面的代码 + + + +```java +class CommandLineArgs { + + /** + * 选项参数列表 + */ + private final Map> optionArgs = new HashMap<>(); + + /** + * 非选项参数列表 + */ + private final List nonOptionArgs = new ArrayList<>(); + + /** + * Add an option argument for the given option name and add the given value to the + * list of values associated with this option (of which there may be zero or more). + * The given value may be {@code null}, indicating that the option was specified + * without an associated value (e.g. "--foo" vs. "--foo=bar"). + * + * 添加 选项参数 + */ + public void addOptionArg(String optionName, @Nullable String optionValue) { + if (!this.optionArgs.containsKey(optionName)) { + this.optionArgs.put(optionName, new ArrayList<>()); + } + if (optionValue != null) { + this.optionArgs.get(optionName).add(optionValue); + } + } + + /** + * Return the set of all option arguments present on the command line. + * 获取选项参数列表 + */ + public Set getOptionNames() { + return Collections.unmodifiableSet(this.optionArgs.keySet()); + } + + /** + * Return whether the option with the given name was present on the command line. + */ + public boolean containsOption(String optionName) { + return this.optionArgs.containsKey(optionName); + } + + /** + * Return the list of values associated with the given option. {@code null} signifies + * that the option was not present; empty list signifies that no values were associated + * with this option. + */ + @Nullable + public List getOptionValues(String optionName) { + return this.optionArgs.get(optionName); + } + + /** + * Add the given value to the list of non-option arguments. + */ + public void addNonOptionArg(String value) { + this.nonOptionArgs.add(value); + } + + /** + * Return the list of non-option arguments specified on the command line. + */ + public List getNonOptionArgs() { + return Collections.unmodifiableList(this.nonOptionArgs); + } + +} +``` + + + + + +在了解 CommandLineArgs 类后再来看 SimpleCommandLinePropertySource 会相对容易. 内部的几个方法就是调用 CommandLineArgs 所提供的方法 + + + +```java +@Override +public String[] getPropertyNames() { + return StringUtils.toStringArray(this.source.getOptionNames()); +} + +@Override +protected boolean containsOption(String name) { + return this.source.containsOption(name); +} + +@Override +@Nullable +protected List getOptionValues(String name) { + return this.source.getOptionValues(name); +} + +@Override +protected List getNonOptionArgs() { + return this.source.getNonOptionArgs(); +} +``` + diff --git a/docs/Spring/clazz/PropertySource/Spring-StubPropertySource.md b/docs/Spring/clazz/PropertySource/Spring-StubPropertySource.md new file mode 100644 index 0000000..7c9529e --- /dev/null +++ b/docs/Spring/clazz/PropertySource/Spring-StubPropertySource.md @@ -0,0 +1,28 @@ +# Spring StubPropertySource + +- Author: [HuiFer](https://github.com/huifer) +- 源码阅读仓库: [SourceHot-spring](https://github.com/SourceHot/spring-framework-read) + + + +- 整体代码如下. + - 通过 StubPropertySource 的 getProperty 方法永远返回null + +```java + public static class StubPropertySource extends PropertySource { + + public StubPropertySource(String name) { + super(name, new Object()); + } + + /** + * Always returns {@code null}. + */ + @Override + @Nullable + public String getProperty(String name) { + return null; + } + } + +``` \ No newline at end of file