SpringBoot 2原理---SpringBoot配置文件的加载原理和优先级

innovus:如何在init design之后新增参考库(lib/lef) 如题,在PR过程中经常会遇到这种问题,时序无法收敛,需要新增一套lvt或者hpc的库,怎么办? 阅读详情

SpringBoot配置文件的加载原理和优先级

我们都知道:

  • SpringBoot 既可以加载指定目录下的配置文件获取配置项;
  • 也可以通过启动参数(VM Options)传入配置项;

在跟踪源代码之前,先提一个问题:
当我们在通过启动参数传入的配置项时候优先使用呢,即会“顶掉”配置文件中的配置?

1.通过启动参数传入配置项

示例:

1.1 application.yml
server:
  port: 8888

spring:
  profiles:
    active: dev
1.2 application-dev.yml
spring:
  think: hello
1.3 在IDEA中使用命令行配置项

VM Options :

-Dserver.port=5555

如下图:
在这里插入图片描述

1.4 启动结果

Tomcat started on port(s): 5555 (http) with context path ‘’

结果: 同时在application.yml 和 启动参数(VM options)中设置 server.port, 最终采用了 启动参数 中的值。

接下来开始从main函数启动处,跟入SpringBoot源码,看看SpringBoot是如何处理的。

2.系统说明

JDK:1.8
SpringBoot 版本: 2.2.2.RELEASE
IDE: IntelliJ IDEA 2018.1

3.启动参数传入配置项

跟踪源码:

可查看如下Spring Boot 2.2.2 版本的执行流程。
SpringBoot2原理—SpringApplication的执行流程

当看到3.6 创建 Environment 节如下代码时候:

ConfigurableEnvironment environment = prepareEnvironment(listeners,
					applicationArguments);
			configureIgnoreBeanInfo(environment);

有截图
在这里插入图片描述

通过IDEA 一行行debug可以看到是在 prepareEnvironment方法执行后,server.port 配置项才被加载入 environment 环境配置中。说明prepareEnvironment方法做的事情就是将server.port 配置项才加载到 environment 环境配置中。因此,我们重新打断点跟入prepareEnvironment方法。

#SpringApplication.java

private ConfigurableEnvironment prepareEnvironment(
			SpringApplicationRunListeners listeners,
			ApplicationArguments applicationArguments) {
		// Create and configure the environment
		//跟入getOrCreateEnvironment()
		ConfigurableEnvironment environment = getOrCreateEnvironment();
		configureEnvironment(environment, applicationArguments.getSourceArgs());
		listeners.environmentPrepared(environment);
		bindToSpringApplication(environment);
		if (!this.isCustomEnvironment) {
			environment = new EnvironmentConverter(getClassLoader())
					.convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());
		}
		ConfigurationPropertySources.attach(environment);
		return environment;
	}

同样的套路,通过debug发现实在getOrCreateEnvironment方法执行后得到server.port的值 。

#SpringApplication.java

private ConfigurableEnvironment getOrCreateEnvironment() {
		if (this.environment != null) {
			return this.environment;
		}
		switch (this.webApplicationType) {
		case SERVLET:
			return new StandardServletEnvironment();
		case REACTIVE:
			return new StandardReactiveWebEnvironment();
		default:
			 //跟入StandardEnvironment
			return new StandardEnvironment();
		}
	}

虚拟机启动参数的加载 是在StandardServletEnvironment 的实例化过程中完成的。
跟入StandardServletEnvironment的实例化过程之前,大家需要先了解 Java模板模式 。
看一下StandardServletEnvironment的类继承关系图(通过IDEA 右键 类名 --> Diagrams --> Show Diagrams Popup 即可显示下图)
在这里插入图片描述

抽象父类AbstractEnvironment的实例化方法中,调用了可由子类继承的customizePropertySources方法。

#AbstractEnvironment.java

 //跟入AbstractEnvironment构造方法
public AbstractEnvironment() {
		customizePropertySources(this.propertySources);
	}

实体化的过程中回过头来调用了子类StandardServletEnvironment的customizePropertySources方法.

#StandardServletEnvironment.java
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);
	}

又调用了父类StandardEnvironment的customizePropertySources方法.

#StandardEnvironment.java

protected void customizePropertySources(MutablePropertySources propertySources) {
		//跟入getSystemProperties()方法
		propertySources.addLast(new MapPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));
		propertySources.addLast(new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
	}

有截图

通过IDEA 的变量监听功能,可以看到正是StandardEnvironment类的getSystemProperties()方法获取到了之前设置的虚拟机启动参数server.port的值。

继续跟进去。

#AbstractEnvironment.java

public Map<String, Object> getSystemProperties() {
		try {
			//跟入
			return (Map) System.getProperties();
		}
#System.java
    public static Properties getProperties() {
        SecurityManager sm = getSecurityManager();
        if (sm != null) {
            sm.checkPropertiesAccess();
        }

        return props;
    }

我们搜索一下有没有什么地方初始化 props。

#System.java

private static Properties props;
    private static native Properties initProperties(Properties props);

发现了静态方法 initProperties,从方法名上即可知道在类被加载的时候 就初始化了 props, 这是个本地方法,继续跟的话需要看对应的C++代码。

回到StandardEnvironment类的customizePropertySources方法。

protected void customizePropertySources(MutablePropertySources propertySources) {
		//public static final String SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME = "systemProperties";
		//跟入MapPropertySource
		propertySources.addLast(new MapPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));
		propertySources.addLast(new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
	}

MutablePropertySources是PropertySources的实现类。

#MutablePropertySources.java

    /**
     * Add the given property source object with lowest precedence.
     * 添加属性源,并使其优先级最低
     */
    public void addLast(PropertySource<?> propertySource) {

再看一下MutablePropertySources的类注释。

/**
 * <p>Where <em>precedence</em> is mentioned in methods such as {@link #addFirst}
 * and {@link #addLast}, this is with regard to the order in which property sources
 * will be searched when resolving a given property with a {@link PropertyResolver}.
 *
 * addFist 和 add Last 会设置属性源的优先级,
 * PropertyResolver解析配置时会根据优先级使用配置源
 * 
 * @author Chris Beams
 * @author Juergen Hoeller
 * @since 3.1
 * @see PropertySourcesPropertyResolver
 */

4.加载指定目录下的配置文件

此时我们已经看到虚拟机的启动参数先添加到系统当中,那么后面添加进来的Property Source属性源的优先级是否比 SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME(systemProperties) 属性源的优先级高呢?

让我们重新回到SpringApplication的prepareEnvironment方法。

##SpringApplication.java

private ConfigurableEnvironment prepareEnvironment(
			SpringApplicationRunListeners listeners,
			ApplicationArguments applicationArguments) {
		// Create and configure the environment
		ConfigurableEnvironment environment = getOrCreateEnvironment();
		configureEnvironment(environment, applicationArguments.getSourceArgs());
		listeners.environmentPrepared(environment);
		bindToSpringApplication(environment);
		if (!this.isCustomEnvironment) {
			environment = new EnvironmentConverter(getClassLoader())
					.convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());
		}
		ConfigurationPropertySources.attach(environment);
		return environment;
	}

在这里插入图片描述
在这里插入图片描述
同样的debug套路发现listeners.environmentPrepared执行后,application.yml 和 application-dev.yml 两个配置文件的配置项都被加载完成,所以我们继续跟入environmentPrepared方法。
在跟入environmentPrepared方法之前,需要了解 Java事件监听机制

跟入environmentPrepared中的源码。

#SpringApplicationRunListeners.java

    public void environmentPrepared(ConfigurableEnvironment environment) {
        for (SpringApplicationRunListener listener : this.listeners) {
            //跟入
            listener.environmentPrepared(environment);
        }
    }
#EventPublishingRunListener.java

    public void environmentPrepared(ConfigurableEnvironment environment) {
        //广播ApplicationEnvrionmentPreparedEvnet事件
        //跟入
        this.initialMulticaster.multicastEvent(new ApplicationEnvironmentPreparedEvent(
                this.application, this.args, environment));
    }
#SimpleApplicationEventMulticaster.java

    public void multicastEvent(ApplicationEvent event) {
        //跟入
        multicastEvent(event, resolveDefaultEventType(event));
    }

    @Override
    public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
        ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
        //注意此时 getApplicationListeners(event, type) 返回结果
        //包含 监听器 *ConfigFileApplicationListener*
                for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
            Executor executor = getTaskExecutor();
            if (executor != null) {
                executor.execute(() -> invokeListener(listener, event));
            }
            else {
                //跟入
                invokeListener(listener, event);
            }
        }
    }

这里解释一下监听器 ConfigFileApplicationListener为什么会有:

getApplicationListeners(event, type)方法执行完成之后,查看所有的监听器如下红框中显示的监听器–ConfigFileApplicationListener 。
在这里插入图片描述

#SimpleApplicationEventMulticaster.java

    /**
     * Invoke the given listener with the given event.
     * 调用对应事件的监听者
     * @param listener the ApplicationListener to invoke
     * @param event the current event to propagate
     * @since 4.1
     */
    protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
        ErrorHandler errorHandler = getErrorHandler();
        if (errorHandler != null) {
            try {
                doInvokeListener(listener, event);
            }
            catch (Throwable err) {
                errorHandler.handleError(err);
            }
        }
        else {
            //跟入
            doInvokeListener(listener, event);
        }
    }

    private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
        try {
            //跟入
            listener.onApplicationEvent(event);
        }
#ApplicationListener.java

    //实现接口的监听器当中,有并跟入ConfigFileApplicationListener的实现
    void onApplicationEvent(E event);
public void onApplicationEvent(ApplicationEvent event) {
		if (event instanceof ApplicationEnvironmentPreparedEvent) {
			//跟入
			onApplicationEnvironmentPreparedEvent(
					(ApplicationEnvironmentPreparedEvent) event);
		}
		if (event instanceof ApplicationPreparedEvent) {
			onApplicationPreparedEvent(event);
		}
	}

	private void onApplicationEnvironmentPreparedEvent(
			ApplicationEnvironmentPreparedEvent event) {
		List<EnvironmentPostProcessor> postProcessors = loadPostProcessors();
		postProcessors.add(this);
		AnnotationAwareOrderComparator.sort(postProcessors);
		for (EnvironmentPostProcessor postProcessor : postProcessors) {
			//跟入:当postProcessor 为 ConfigFileApplicationListener
			postProcessor.postProcessEnvironment(event.getEnvironment(),
					event.getSpringApplication());
		}
	}
#ConfigFileApplicationListener.java

public void postProcessEnvironment(ConfigurableEnvironment environment,
			SpringApplication application) {
		//跟入
		addPropertySources(environment, application.getResourceLoader());
	}

protected void addPropertySources(ConfigurableEnvironment environment,
			ResourceLoader resourceLoader) {
		//environment的属性源中包含 systemProperties 属性源 即包含 server.port启动参数
		RandomValuePropertySource.addToEnvironment(environment);
		 //跟入 load()方法
		new Loader(environment, resourceLoader).load();
	}

跟入load之前,需要了解 java lambda表达式。

#ConfigFileApplicationListener.java

public void load() {
			this.profiles = new LinkedList<>();
			this.processedProfiles = new LinkedList<>();
			this.activatedProfiles = false;
			this.loaded = new LinkedHashMap<>();
			initializeProfiles();
			while (!this.profiles.isEmpty()) {
				Profile profile = this.profiles.poll();
				if (profile != null && !profile.isDefaultProfile()) {
					addProfileToEnvironment(profile.getName());
				}
				load(profile, this::getPositiveProfileFilter,
						addToLoaded(MutablePropertySources::addLast, false));
				this.processedProfiles.add(profile);
			}
			resetEnvironmentProfiles(this.processedProfiles);
			//跟入
			load(null, this::getNegativeProfileFilter,
					addToLoaded(MutablePropertySources::addFirst, true));
			addLoadedPropertySources();
		}
#ConfigFileApplicationListener.java

	private void load(Profile profile, DocumentFilterFactory filterFactory,
				DocumentConsumer consumer) {
			//getSearchLocations()默认返回:
            //[./config/, file:./, classpath:/config/, classpath:/]
            //即搜索这些路径下的文件
			getSearchLocations().forEach((location) -> {
				boolean isFolder = location.endsWith("/");
				//getSearchNames()返回:application
				Set<String> names = isFolder ? getSearchNames() : NO_SEARCH_NAMES;
				//跟入load(.....)
				names.forEach(
						(name) -> load(location, name, profile, filterFactory, consumer));
			});
		}
#ConfigFileApplicationListener.java

private void load(String location, String name, Profile profile,
				DocumentFilterFactory filterFactory, DocumentConsumer consumer) {
			//name默认为:application,所以这个if分支略过
			if (!StringUtils.hasText(name)) {
				for (PropertySourceLoader loader : this.propertySourceLoaders) {
					if (canLoadFileExtension(loader, location)) {
						load(loader, location, profile,
								filterFactory.getDocumentFilter(profile), consumer);
						return;
					}
				}
			}
			Set<String> processed = new HashSet<>();
			 //this.propertySourceLoaders: PropertiesPropertySourceLoader,YamlPropertySourceLoader
			for (PropertySourceLoader loader : this.propertySourceLoaders) {
				//PropertiesPropertySourceLoader.getFileExtensions(): properties, xml
                //YamlPropertySourceLoader.getFileExtensions(): yml, yaml
				for (String fileExtension : loader.getFileExtensions()) {
					//location: [./config/, file:./, classpath:/config/, classpath:/]
                    //name: application
					if (processed.add(fileExtension)) {
						//profile: null, dev
                    //相当于对(location, fileExtension, profile)做笛卡尔积,
                    //遍历每一种可能,然后加载
                    //加载文件的细节在loadForFileExtension中完成
						loadForFileExtension(loader, location + name, "." + fileExtension,
								profile, filterFactory, consumer);
					}
				}
			}
		}

继续跟入 loadForFileExtension 方法,可以了解载入一个配置文件的更多细节。

回到之前的load()方法。

#ConfigFileApplicationListener.java

public void load() {
			this.profiles = new LinkedList<>();
			this.processedProfiles = new LinkedList<>();
			this.activatedProfiles = false;
			this.loaded = new LinkedHashMap<>();
			initializeProfiles();
			while (!this.profiles.isEmpty()) {
				Profile profile = this.profiles.poll();
				if (profile != null && !profile.isDefaultProfile()) {
					addProfileToEnvironment(profile.getName());
				}
				load(profile, this::getPositiveProfileFilter,
						addToLoaded(MutablePropertySources::addLast, false));
				this.processedProfiles.add(profile);
			}
			resetEnvironmentProfiles(this.processedProfiles);
			load(null, this::getNegativeProfileFilter,
					addToLoaded(MutablePropertySources::addFirst, true));
			//跟入
			addLoadedPropertySources();
		}
#ConfigFileApplicationListener.java

private void addLoadedPropertySources() {
			////destination: 进入ConfigFileApplicationListener监听器前已有的配置 
            //即destination中包含 systemProperties 配置源
			MutablePropertySources destination = this.environment.getPropertySources();
			//loaded: 此次监听通过扫描文件加载进来的配置源
            //loaded: application.yml, appcalition-dev.yml
			List<MutablePropertySources> loaded = new ArrayList<>(this.loaded.values());
			//倒序后 loaded: application-dev.yml, application.yml
			Collections.reverse(loaded);
			String lastAdded = null;
			Set<String> added = new HashSet<>();
			//先处理 application-dev.yml
			for (MutablePropertySources sources : loaded) {
				for (PropertySource<?> source : sources) {
					if (added.add(source.getName())) {
						//第一次进入: lastAdded:null
						//跟入
						addLoadedPropertySource(destination, lastAdded, source);
						//第一次遍历结束: lastAdded: application-dev
						lastAdded = source.getName();
					}
				}
			}
		}

		private void addLoadedPropertySource(MutablePropertySources destination,
				String lastAdded, PropertySource<?> source) {
			if (lastAdded == null) {
				if (destination.contains(DEFAULT_PROPERTIES)) {
					destination.addBefore(DEFAULT_PROPERTIES, source);
				}
				else {
					//第一次进入: 把application-dev.yml至于最低优先级
					destination.addLast(source);
				}
			}
			else {
				//第二次进入:
                //让 application.yml 优先级比 application-dev.yml 低
				destination.addAfter(lastAdded, source);
			}
		}

执行后得到各自的优先级,如下图:

在这里插入图片描述
systemProperties优先级高,解析器会优先使用 systemProperties中的 server.port 配置项即 5555 所以最终Tomcat 启动端口是 5555 .

从图中也可以看出,如果application.yml 和 application-dev.yml中有相同的配置项,会优先采用application-dev.yml中的配置项。

在这里插入图片描述

精读204页华为的流程管理(文末附下载链接) 链接:https://pan.baidu.com/s/1eEwdBR5c0PIxkOrNhDZcGg?pwd=wha2 提取码:wha2 复制这段内容后打开百度网盘手机App,操作更方便哦。,以提升企业运营效率和竞争力,同时解决了诸多业务痛点,为华为的全球化发展提供了有力支撑。华为的流程管理对其发展起着关键作用,通过构建完善的流程体系,提升了企业运营效率与竞争力。华为的流程管理在企业发展中至关重要,其围绕。,并通过流程变革不断优化。在流程管理过程中,强调。构建了全面的流程体系。 阅读详情

相关推荐

300m半径无人机单兵侦测设备技术详解

300m半径无人机单兵侦测设备凭借其卓越的侦测性能、高效的识别能力、便捷的告警方式以及广泛的应用场景,成为现代军事、安保及应急救援领域的重要装备。300m半径无人机单兵侦测设备,融合了最新的无人机技术、高精度传感技术与实时数据处理技术,为单兵作战、巡逻及侦察任务提供了前所未有的视野与效率。该设备通过无人机搭载的高性能侦测模块,能够在复杂环境中实现300米范围内的精准侦测,大幅提升单兵的战场感知能力和决策效率。设备为被动式探测设备,确保安静安全运行,不暴露目标 设备耗电功率小,可长时间在野外使用。

专注多旋翼、复合翼无人机技术研究,从事低空经济行业。 1120

Springboot配置文件加载原理及流程【源码分析】

序言 Springboot开箱即用,使用起来十分的便捷,但是如果我们只是知其然不知其所以然,那我们将很难熟练的驾驭它,接下来我就为大家以debug的形式为大家讲解一下Springboot配置文件的加载流程。并为大家讲解一下springboot是怎样将我们配置在yml文件中的变量赋值给对应的属性的。本文篇幅有点长,还请大家耐心观看。 环境准备 准备一个Springboot项目,并配置多个配置文件 在application.yml配置文件中指定项目以dev环境进行启动 在每个配置文件中都配置一个相同的配置

Mr_Liu946的博客 6530

Windows Server 2012评估版过期自动关机问题:两种高效解决方案详解

本文针对Windows Server 2012评估版过期导致的自动关机问题,提供了两种高效解决方案。一是通过slmgr.vbs命令重置授权,临时延长评估期;二是使用DISM工具将评估版转换为正式版,一劳永逸。文章详细解析了两种方法的操作步骤、注意事项及适用场景,帮助用户快速恢复服务器稳定运行。

pytorchlight8的博客 1195

spring boot的application.yml和application-dev.yml

对于这两个文件的优先级,如果只有application.yml文件,则全部使用这里面的文件配置,如果在application.yml中指定了profiles的active文件,那么就按照这个指定的文件进行寻找。默认情况下,一开始创建spring boot 项目只有application.properties文件,没有xxxx.yml文件。也就是先寻找active指定的配置文件里面的内容,如果没有找到则去找application.yml中的内容。我们创建application.yml文件,并写上如下代码。

城南蝈蝈 3127

jaka+realsense+aruco+手眼标定(python)

第二次重建了项目的手眼标定部分……有很多第一次记录遗漏的地方,在此补充。

drivenzyw的博客 2122

ZBrush 2021来了

这次给大家带来的是:zbrush2021.1.1 win安装教程 1.下载压缩包之后解压到文件夹当中,然后打开ZBrush_2021_Installer.exe进行软件安装, 如下图 2.在这里我们保持默认的简体中文版即可,然后点击确认,如下图 3.第三步我们点击前进即可,如下图 4.第四步我们来到许可协议,在这里我们点击我接受此协议,然后点击前进,如下图 5.第五步我们来到安装目录,在这里我们可以设置安装路径,如下图 6.在这里我将安装目录修改安装到E盘为例,然后点击下一

3D游戏建模 1188

springboot配置文件及默认的加载优先级

SpringBoot 配置文件类型 SpringBoot 不同位置的配置文件默认读取优先级 SpringBoot 特殊的配置文件读取方式(指定读取等)

Chakyrd的博客 2769

mybaits-plus通用CRUD详解及代码案例

文章目录mybaitsplus通用CRUD插入操作方法定义测试用例mybaitsplus主键生成策略设置自增主键设置输入主键:UUID:ID_WORKER_STR:ID_WORKER:更新操作根据id更新方法定义:方法步骤根据条件更新方法定义:更新步骤:根据条件更新(可以更新NULL)删除操作根据id删除方法定义:删除步骤:根据 entity 条件删除方法定义:删除步骤:根据ID 批量删除方法定义:删除步骤:查询操作根据id查询方法定义:查询步骤:根据id批量查询方法定义:查询步骤:根据 entity 条件

流楚丶格念的博客 3405

Spring Boot不同配置文件名和配置文件所在路径的优先级

springboot配置文件优先级,springboot配置文件和配置中心优先级,springboot配置文件名优先级,springcloud配置文件优先级,springcloud配置中心和配置文件优先级,springboot配置文件路径优先级,springboot配置文件的路径优先级,springboot配置文件不同文件名的区别,springboot不同配置文件名的区别,springboot不同配置文件的优先级

aiguoba的博客 1439

单板电源设计(LDO、DC/DC)

高速电路设计的电源架构 在电路设计中,一块单板往往涉及多种电源,常见的如5V/3.3V/2.5V/1.8V/1.5V/1.2V/1V0.9V/0.75V等,如此多种类的电源不可能都直接通过背板从电源板获得。一般,单板仅有一种或者两种输入电源,如48V或12V,再由它们产生单板上器件所需要的电源。 单板如何由输入电源生成所需电源,常见有两种架构:集中式电源架构和分布式电源架构。 ...

sinat_15677011的博客 8331

【精细解读】xapp585(多通道LVDS接口ADC)

xapp585的参考设计有Verilog和VHDL两种源码。

FPGA艺术家的博客 532

springboot中bootstrap和application配置文件的加载顺序

springboot中bootstrap和application配置文件的加载顺序

weichangIT的博客 4118

【Python】秋招机考 —— 2025/9/17 华为 AI 方向

秋招机考,华为 AI,使用 Python 完成编程。

一杯水果茶!足矣~ 1166

springboot3项目启动配置文件解析顺序与原理及与springboot2主要区别

Spring Boot3通过简化配置加载逻辑、增强外部化配置能力,提升了多环境部署的灵活性。与Spring Boot2相比,其核心变化集中在多文档YAML处理、外部配置覆盖规则和激活语法上。实际开发中需根据这些差异调整配置策略,以充分利用新版本的优势。Spring Boot3项目能够更高效地管理和加载配置文件,提升开发和维护效率。

T_TO_O-的专栏 835

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

SpringBoot配置加载原理及顺序

目录配置源及优先级顺序yaml和properties配置文件优先级源码加载和管理原理动态配置 配置源及优先级顺序 (优先级一次从高到低) 用户目录下 ~/.spring-boot-devtools.properties 文件的全局配置:对机器上所有应用生效 @TestPropertySource 是Spring的类注解,用于标注集成测试类 @SpringBootTest 注解类用于局部应用测试 命令行参数 环境变量或系统变量嵌入的json配置:SPRING_APPLICATION_JSON Servlet

u012464024的博客 708

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

springboot2.7.x 系列之配置文件加载

最终中的命令行参数Nacos 配置) - 如果存在- 特定环境配置- 默认配置- Bootstrap 配置系统环境变量系统属性是配置加载的入口,负责初始化并触发监听器。Bootstrap 上下文通过独立机制加载和 Nacos 配置,优先级高于。Nacos 集成通过动态注入远程配置,实现配置的集中管理。配置优先级由列表顺序决定,命令行参数 > Nacos >> 系统属性。

JAVA爱好者的专栏 352

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

SpringBoot配置文件加载顺序:一场配置界的权力游戏

SpringBoot配置加载顺序遵循"外部优先"原则,从高到低依次为:命令行参数、系统环境变量、随机属性、应用配置文件等。配置文件位置优先级为:命令行指定>项目config目录>类路径config包>类路径根目录,其中.properties文件优先于.yml。微服务环境下bootstrap配置文件优先加载。理解这一机制可避免配置冲突,实现灵活部署。最佳实践包括:通用配置放内部、环境相关配置放外部,敏感信息使用专业工具管理。

热爱技术、喜欢学习、乐于分享 659

SpringBoot全局配置文件加载原理详解(万字源码分析)

SpringBoot全局配置文件加载原理详解(源码分析) SpringBoot全局配置文件加载原理详解(源码分析)SpringBoot配置文件初见配置文件位置的优先级properties与yaml的优先级对比SpringBoot配置文件的加载原理源码分析加载ApplicationListener实现类监听器ConfigFileApplicationListener监听器监听ApplicationEnvironmentPreparedEvent事件发送事件与监听器的触发ApplicationStarting

大数据开发、JAVA开发、人工智能AI 2544

SpringBoot加载配置文件原理分析

本文是基于SpringBoot2.4.0之前的版本分析的,2.4.0之后有所不同 想必大家对SpringBoot中的application.properties(或application.yaml)文件都是再熟悉不过的了。它是应用的配置文件,我们可以把需要的一些配置信息都写在这个文件里面,需要的时候,我们可以通过@Value注解来直接获取即可,那这个文件是什么时候以及如何被应该加载的呢?这一直是我之前疑惑的地方,也是终于有时间对这一部分进行了详细的源码分析。 原理先行 整个配置文件的加载过程其实就是一个.

ITlikeyou的博客 3699

springboot配置文件加载顺序_从SpringBoot源码分析 配置文件的加载原理和优先级

本文从SpringBoot源码分析 配置文件的加载原理和配置文件的优先级 跟入源码之前,先提一个问题: SpringBoot 既可以加载指定目录下的配置文件获取配置项,也可以通过启动参数(VM Options)传入配置项,为什么通过启动参数传入的配置项会“顶掉”配置文件中的配置?示例:application.yml server.port: 8888 spring.profiles.acti...

weixin_39976081的博客 451

SpringBoot(十二)源码角度解析配置文件加载优先级

Spring Boot启动会扫描application.properties或者application.yml文件作为Spring Boot的默认配置文件。在使用过程中会涉及到各种各样的配置,本篇则主要针对配置路径,看一下文件加载的前后顺序。多个配置文件配置了同样得值,会加载哪一个呢? 一、内部配置的加载顺序 1)配置文件前后顺序执行测试 file:/config/ file:/ classpath:/config/ classpath:/ 以上顺序按照优先级从高到低的顺序,所有位置的文件

不管风吹浪打,胜似闲庭信步 1769

SpringBoot加载配置文件application.yml的过程及原理(相同属性如何加载)

SpringBoot的yml文件如何被加载,以及加载原理

莫失莫忘的博客 1万+

Spring Boot的配置文件加载优先级

详细介绍了Spring Boot的配置文件的加载优先级。

终生学习践行者 5574

SpringBoot启动如何加载application.yml配置文件

一、前言 在spring时代配置文件的加载都是通过web.xml配置加载的(Servlet3.0之前),可能配置方式有所不同,但是大多数都是通过指定路径的文件名的形式去告诉spring该加载哪个文件; <context-param>   <param-name>contextConfigLocation</param-name>   &lt...

likunpeng6656201的博客 3957

springboot配置文件的加载先后顺序

springboot配置文件的加载先后顺序 1,内部加载文件 springboot启动会扫描以下位置的application.properties或者application.yml文件作为Spring boot的默认配置文件 –file:./config/ –file:./ –classpath:/config/ –classpath:/ 优先级由高到底,高优先级的配置会覆盖低优先级的配置;例如: SpringBoot会从这四个位置全部加载主配置文件,也就是说如果所有的文件配置了一样的信息,会进行覆盖,但

lishangqing的博客 5571

springboot源码解读与原理分析_从SpringBoot源码分析 配置文件的加载原理和优先级...

本文从SpringBoot源码分析 配置文件的加载原理和配置文件的优先级 跟入源码之前,先提一个问题: SpringBoot 既可以加载指定目录下的配置文件获取配置项,也可以通过启动参数(VM Options)传入配置项,为什么通过启动参数传入的配置项会“顶掉”配置文件中的配置?示例:application.yml server.port: 8888 spring.profiles.acti...

weixin_39642990的博客 791
上一篇: git连接github完整教程
下一篇: docker+jenkins构建项目历史记录(Build History)时间与控制台日志时间不一致问题
Spring的思念
博客等级 码龄7年 80粉丝 143原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值