首页 > 其他分享 >SpringBoot配置文件加载过程

SpringBoot配置文件加载过程

时间:2023-09-27 12:55:42浏览次数:35  
标签:属性 name 配置文件 String propertySources new 加载 public SpringBoot

前置知识

配置属性抽象和各种实现类

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的结构

image-20230925202804163

// 抽象类的构造方法中会通过模板方法的方式调用 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

相关文章

  • UnityGLTF插件加载模型时,emissiveFactor解析报错
    项目中遇到使用 UnityGLTF插件加载GLTF模型时报错,如下图: 根据报错信息,我们找到GLTF文件中,第[五]个材质的描述:{"name":"11_-_Default木质长廊1.bmp_alpha","occlusionTexture":{"index":0,"texCoord":1},......
  • 工作流如何实现?集成?springboot+vue+activiti技术栈
    前言activiti工作流引擎项目,企业erp、oa、hr、crm等企事业办公系统轻松落地,一套完整并且实际运用在多套项目中的案例,满足日常业务流程审批需求。一、项目形式springboot+vue+activiti集成了activiti在线编辑器,流行的前后端分离部署开发模式,快速开发平台,可插拔工作流服务。工作......
  • UnityGLTF插件加载模型时,OcclusionTexture贴图显示错误的问题处理
    工作中遇到使用UnityGLTF插件加载GLTF模型时,贴图显示错误的问题,如下图 检查材质时发现,把OcclusionTexture去掉就看起来正常了  看来是插件对OcclusionTexture的解析出了问题, 那么我们来看一下,GLTF中对OcclusionTexture的描述片段,是这样:"name":"5木质长廊1.bmp","o......
  • 7、springboot使用MessageSource国际化提示
    目录springboot使用MessageSource国际化提示1、MessageSource源码2、yml配置MessageSource3、创建MessagesUtils工具类简化使用springboot使用MessageSource国际化提示1、MessageSource源码MessageSource是spring自带的一个接口,源码如下packageorg.springframework.context;......
  • SpringBoot | 拦截机制
    欢迎参观我的博客,一个Vue与SpringBoot结合的产物:https://poetize.cn博客:https://gitee.com/littledokey/poetize-vue2.git聊天室:https://gitee.com/littledokey/poetize-im-vue3.git后端:https://gitee.com/littledokey/poetize.git七牛云登录/注册地址(文件服务器,CDN):https:/......
  • SpringBoot | Bean生命周期
    欢迎参观我的博客,一个Vue与SpringBoot结合的产物:https://poetize.cn博客:https://gitee.com/littledokey/poetize-vue2.git聊天室:https://gitee.com/littledokey/poetize-im-vue3.git后端:https://gitee.com/littledokey/poetize.git七牛云登录/注册地址(文件服务器,CDN):https:/......
  • centos7 网卡配置文件解读
    借的图 另外,/etc/resolv.conf 是DNS客户机配置文件,用于设置DNS服务器的IP地址及DNS域名,还包含了主机的域名搜索顺序它的格式很简单,每行以一个关键字开头,后接一个或多个由空格隔开的参数 nameserver 8.8.8.8借鉴的:https://blog.csdn.net/lcr_happy/article/details/......
  • Idea+SpringBoot控制台调试打印sql语句
    在application.yml中添加:logging:level:com.xiaobai.stock.mapper:DEBUG//注意:':'后有空格,不能省略mapper:运行时控制台 ......
  • SpringBoot | 加密算法使用示例
    欢迎参观我的博客,一个Vue与SpringBoot结合的产物:https://poetize.cn博客:https://gitee.com/littledokey/poetize-vue2.git聊天室:https://gitee.com/littledokey/poetize-im-vue3.git后端:https://gitee.com/littledokey/poetize.git七牛云登录/注册地址(文件服务器,CDN):https:/......
  • SpringBoot | Dubbo之Filter使用示例
    欢迎参观我的博客,一个Vue与SpringBoot结合的产物:https://poetize.cn博客:https://gitee.com/littledokey/poetize-vue2.git聊天室:https://gitee.com/littledokey/poetize-im-vue3.git后端:https://gitee.com/littledokey/poetize.git七牛云登录/注册地址(文件服务器,CDN):https:/......