前置知识
配置属性抽象和各种实现类
PropertySource<T>
下面是 抽象类属性源 和 它的两个内部实现类 介绍
// 抽象父类
public abstract class PropertySource<T> {
/** 属性源名称 **/
protected final String name;
/** 属性源数据 **/
protected final T source;
/** 从source里面获取Property,要public T getSource(){}区别开
getSource是获取整个source字段,getProperty是从source里面查询指定Property **/
@Nullable
public abstract Object getProperty(String name);
// PropertySource的内部实现类 主要作用是占据一个位置,后面再用实际的属性源替换
/** 在应用程序上下文创建时无法急切地初始化实际属性源的情况下,可以将属性源用作占位符。
例如,ServletContext-based属性源必须等到ServletContext对象对其封闭的Application ationContext可用。
在这种情况下,应该使用存根来保存属性源的预期默认位置/顺序,然后在上下文刷新期间替换。 **/
public static class StubPropertySource extends PropertySource<Object> {
public StubPropertySource(String name) {
super(name, new Object());
}
/**
* 重写了父类的getProperty方法,直接返回 Null 值 ,
*/
@Override
@Nullable
public String getProperty(String name) {
return null;
}
}
/**用于集合比较目的的PropertySource实现。 主要的方法实现都直接抛出异常 */
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<T>
可枚举的抽象子类
/** 子类通过通过实现 getPropertyNames() 方法获取到属性源的所有 Property名称,
然后通过遍历可以枚举所有 Property, 大多数框架提供的属性源实现都是可枚举的 */
public abstract class EnumerablePropertySource<T> extends PropertySource<T> {
/** 返回源对象包含的所有属性的名称(从不为空) */
public abstract String[] getPropertyNames();
@Override
public boolean containsProperty(String name) {
/** 通过 getPropertyNames() 返回 查询是否包含指定的 Property */
return ObjectUtils.containsElement(getPropertyNames(), name);
}
}
CompositePropertySource
复合属性源
/** 迭代一组属性源实例的复合属性源实现。在多个属性源共享相同名称的情况下是必要的, */
public class CompositePropertySource extends EnumerablePropertySource<Object> {
private final Set<PropertySource<?>> propertySources = new LinkedHashSet<>();
/** 这个实现类本质就是多个 PropertySource 聚合到一起,共用一个 name 属性,链表内的属性源的 name 属性都会被忽略。
然后根据这个特点,重新实现了父类的主要方法,如: getPropertyNames ,containsProperty 等
最后 再有添加了一些操作propertySources链表的方法,如: addPropertySource,getPropertySources等*/
}
配置加载过程:
// 这一步会生成一个完整的 ConfigurableEnvironment 对象
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
一、生成Environment对象
生成一个Environment实现类对象,根据不同的类型初始化的实现类不同,内部逻辑也稍有不同
// 根据不同的环境生成不同类型的 ConfigurableEnvironment 实现
ConfigurableEnvironment environment = getOrCreateEnvironment();
// 核心代码
switch (this.webApplicationType) {
case SERVLET:
// 基于servlet的Web应用程序运行,并应启动嵌入式servlet Web服务器
return new StandardServletEnvironment();
case REACTIVE:
// 响应式Web应用程序运行,并应启动嵌入式响应式Web服务器
return new StandardReactiveWebEnvironment();
default:
return new StandardEnvironment();
}
Environment的结构
// 抽象类的构造方法中会通过模板方法的方式调用 customizePropertySources方法,在不同的子类实现中,会初始化不同的配置源
protected void customizePropertySources(MutablePropertySources propertySources){}
public AbstractEnvironment() {
customizePropertySources(this.propertySources);
}
// org.springframework.core.env.StandardEnvironment
// 这个里面会添加systemEnvironment(系统变量),systemProperties(系统属性)两个配置源
@Override
protected void customizePropertySources(MutablePropertySources propertySources) {
propertySources.addLast(
new PropertiesPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));
propertySources.addLast(
new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
}
//org.springframework.web.context.support.StandardServletEnvironment
//这个里面会添加servletContextInitParams(Servlet上下文参数),servletConfigInitParams(Servlet配置参数),jndiProperties三个配置源
@Override
protected void customizePropertySources(MutablePropertySources propertySources) {
propertySources.addLast(new StubPropertySource(SERVLET_CONFIG_PROPERTY_SOURCE_NAME));
propertySources.addLast(new StubPropertySource(SERVLET_CONTEXT_PROPERTY_SOURCE_NAME));
if (JndiLocatorDelegate.isDefaultJndiEnvironmentAvailable()) {
propertySources.addLast(new JndiPropertySource(JNDI_PROPERTY_SOURCE_NAME));
}
super.customizePropertySources(propertySources);
}
二、配置环境变量
// org.springframework.boot.SpringApplication#configureEnvironment
configureEnvironment(environment, applicationArguments.getSourceArgs());
添加转换服务
// 添加转换服务
if (this.addConversionService) {
ConversionService conversionService = ApplicationConversionService.getSharedInstance();
environment.setConversionService((ConfigurableConversionService) conversionService);
}
// 使用适用于大多数Spring Boot应用程序的格式化程序和转换器配置给定的FormatterRegister
public static void configure(FormatterRegistry registry) {
//添加各种默认的转换器,具体作用后续再研究
DefaultConversionService.addDefaultConverters(registry);
DefaultFormattingConversionService.addDefaultFormatters(registry);
addApplicationFormatters(registry);
addApplicationConverters(registry);
}
配置属性源
此处会添加默认配置和命令行配置源
configurePropertySources(environment, args);
// 添加默认配置属性
if (this.defaultProperties != null && !this.defaultProperties.isEmpty()) {
sources.addLast(new MapPropertySource("defaultProperties", this.defaultProperties));
}
// 添加命令行配置属性
if (this.addCommandLineProperties && args.length > 0) {
String name = CommandLinePropertySource.COMMAND_LINE_PROPERTY_SOURCE_NAME;
if (sources.contains(name)) {
PropertySource<?> source = sources.get(name);
CompositePropertySource composite = new CompositePropertySource(name);
composite.addPropertySource(
new SimpleCommandLinePropertySource("springApplicationCommandLineArgs", args));
composite.addPropertySource(source);
sources.replace(name, composite);
}
else {
sources.addFirst(new SimpleCommandLinePropertySource(args));
}
}
添加激活状态配置文件
// 为此应用程序环境配置哪些配置文件处于活动状态(或默认处于活动状态)。在配置文件处理期间,可以通过spring. profile.active属性激活其他配置文件
protected void configureProfiles(ConfigurableEnvironment environment, String[] args) {
Set<String> profiles = new LinkedHashSet<>(this.additionalProfiles);
profiles.addAll(Arrays.asList(environment.getActiveProfiles()));
environment.setActiveProfiles(StringUtils.toStringArray(profiles));
}
org.springframework.boot.context.properties.source.ConfigurationPropertySources#attach
标签:属性,name,配置文件,String,propertySources,new,加载,public,SpringBoot
From: https://www.cnblogs.com/xysgo/p/17732443.html