SpringBoot源码解析(四):解析应用参数args

SpringBoot源码系列文章

SpringBoot源码解析(一):SpringApplication构造方法

SpringBoot源码解析(二):引导上下文DefaultBootstrapContext

SpringBoot源码解析(三):启动开始阶段

SpringBoot源码解析(四):解析应用参数args


目录

  • 前言
  • 一、入口
  • 二、默认应用程序参数DefaultApplicationArguments
    • 1、功能概述
    • 2、使用示例
    • 3、接口ApplicationArguments
    • 4、实现类DefaultApplicationArguments
  • 四、Source
    • 1、属性源PropertySource
    • 2、枚举属性源EnumerablePropertySource
    • 3、命令行属性源CommandLinePropertySource
    • 4、简单命令行属性源SimpleCommandLinePropertySource
  • 五、解析参数原理
    • 1、解析方法
    • 2、解析参数的存储和访问
    • 3、实际应用
  • 总结

前言

  前文深入解析了SpringBoot启动的开始阶段,包括获取和启动应用启动监听器、事件与广播机制,以及如何通过匹配监听器实现启动过程各阶段的自定义逻辑。接下来,我们将探讨SpringBoot启动类main函数中的参数args的作用及其解析过程

SpringBoot版本2.7.18SpringApplication的run方法的执行逻辑如下,本文将详细介绍第3小节:解析应用参数

// SpringApplication类方法
public ConfigurableApplicationContext run(String... args) {// 记录应用启动的开始时间long startTime = System.nanoTime();// 1.创建引导上下文,用于管理应用启动时的依赖和资源DefaultBootstrapContext bootstrapContext = createBootstrapContext();ConfigurableApplicationContext context = null;// 配置无头模式属性,以支持在无图形环境下运行// 将系统属性 java.awt.headless 设置为 trueconfigureHeadlessProperty();// 2.获取Spring应用启动监听器,用于在应用启动的各个阶段执行自定义逻辑SpringApplicationRunListeners listeners = getRunListeners(args);// 启动开始方法(发布开始事件、通知应用监听器ApplicationListener)listeners.starting(bootstrapContext, this.mainApplicationClass);try {// 3.解析应用参数ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);// 4.准备应用环境,包括读取配置文件和设置环境变量ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);// 配置是否忽略 BeanInfo,以加快启动速度configureIgnoreBeanInfo(environment);// 5.打印启动BannerBanner printedBanner = printBanner(environment);// 6.创建应用程序上下文context = createApplicationContext();// 设置应用启动的上下文,用于监控和管理启动过程context.setApplicationStartup(this.applicationStartup);// 7.准备应用上下文,包括加载配置、添加 Bean 等prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);// 8.刷新上下文,完成 Bean 的加载和依赖注入refreshContext(context);// 9.刷新后的一些操作,如事件发布等afterRefresh(context, applicationArguments);// 计算启动应用程序的时间,并记录日志Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);if (this.logStartupInfo) {new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);}// 10.通知监听器应用启动完成listeners.started(context, timeTakenToStartup);// 11.调用应用程序中的 `CommandLineRunner` 或 `ApplicationRunner`,以便执行自定义的启动逻辑callRunners(context, applicationArguments);}catch (Throwable ex) {// 12.处理启动过程中发生的异常,并通知监听器handleRunFailure(context, ex, listeners);throw new IllegalStateException(ex);}try {// 13.计算应用启动完成至准备就绪的时间,并通知监听器Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);listeners.ready(context, timeTakenToReady);}catch (Throwable ex) {// 处理准备就绪过程中发生的异常handleRunFailure(context, ex, null);throw new IllegalStateException(ex);}// 返回已启动并准备就绪的应用上下文return context;
}

一、入口

  • 将main方法的参数args封装成一个对象DefaultApplicationArguments,以便方便地解析和访问启动参数
// 3.解析应用参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);

二、默认应用程序参数DefaultApplicationArguments

1、功能概述

  DefaultApplicationArguments是SpringBoot中的一个类,用于处理启动时传入的参数。它实现了ApplicationArguments接口,并提供了一些便捷的方法来访问传入的命令行参数选项参数

// 3.解析应用参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
  • 解析命令行参数:将 main 方法中的 args 参数解析成选项参数和非选项参数,方便应用在启动时读取外部传入的配置
  • 访问选项参数:支持以--key=value格式的选项参数,通过方法getOptionNames()getOptionValues(String name)获取特定的选项及其值
  • 访问非选项参数:对于不以--开头的参数,可以通过getNonOptionArgs()获取它们的列表

2、使用示例

  • 假设我们在命令行中运行应用,传递了一些参数
java -jar myapp.jar --server.port=8080 arg1 arg2
  • 在代码中,我们可以使用DefaultApplicationArguments来解析这些参数
public static void main(String[] args) {DefaultApplicationArguments appArgs = new DefaultApplicationArguments(args);// 获取所有选项参数名称System.out.println("选项参数:" + appArgs.getOptionNames());  // 输出: ["server.port"]// 获取指定选项的值(所有以 `--` 开头的选项参数名称)System.out.println("server.port 值:" + appArgs.getOptionValues("server.port"));  // 输出: ["8080"]// 获取非选项参数(所有不以 `--` 开头的参数,通常用于传递无标记的参数值)System.out.println("非选项参数:" + appArgs.getNonOptionArgs());  // 输出: ["arg1", "arg2"]
}

3、接口ApplicationArguments

  • ApplicationArguments是DefaultApplicationArguments类的父接口
// 提供对用于运行应用的参数的访问。
public interface ApplicationArguments {// 返回传递给应用程序的原始未处理参数String[] getSourceArgs();// 返回所有选项参数的名称Set<String> getOptionNames();// 返回解析的选项参数集合中是否包含具有给定名称的选项boolean containsOption(String name);// 返回与给定名称的选项参数关联的值集合List<String> getOptionValues(String name);// 返回解析的非选项参数集合List<String> getNonOptionArgs();
}
  • getOptionNames():返回所有选项参数的名称
    • 例如:参数是"--foo=bar --debug",则返回["foo", "debug"]
  • getOptionValues(String name):返回与给定名称的选项参数关联的值集合
    • 如果选项存在但没有值(例如:"--foo"),返回一个空集合
    • 如果选项存在且有单一值(例如:"--foo=bar"),返回一个包含一个元素的集合["bar"]
    • 如果选项存在且有多个值(例如:"--foo=bar --foo=baz"),返回包含每个值的集合["bar", "baz"]
    • 如果选项不存在,返回null
  • getNonOptionArgs():返回解析的非选项参数集合

4、实现类DefaultApplicationArguments

  • 代码很简单,对外暴露使用DefaultApplicationArguments,内部实现都在Source
// ApplicationArguments的默认实现类,用于解析应用程序启动时传入的参数。
public class DefaultApplicationArguments implements ApplicationArguments {private final Source source; // 用于解析和存储参数的内部辅助类private final String[] args; // 启动时传入的原始参数// 构造函数,使用传入的参数数组初始化对象public DefaultApplicationArguments(String... args) {Assert.notNull(args, "Args must not be null"); // 确保传入参数不为 nullthis.source = new Source(args); // 使用内部类 Source 解析参数this.args = args; // 保存原始参数}// 获取原始未处理的参数数组@Overridepublic String[] getSourceArgs() {return this.args;}// 获取所有选项参数的名称集合@Overridepublic Set<String> getOptionNames() {String[] names = this.source.getPropertyNames();// 该集合不能被修改(即添加、删除元素等操作会抛出 UnsupportedOperationException 异常)return Collections.unmodifiableSet(new HashSet<>(Arrays.asList(names)));}// 检查是否包含指定名称的选项参数@Overridepublic boolean containsOption(String name) {return this.source.containsProperty(name);}// 获取指定名称的选项参数的值集合@Overridepublic List<String> getOptionValues(String name) {List<String> values = this.source.getOptionValues(name);return (values != null) ? Collections.unmodifiableList(values) : null;}// 获取所有非选项参数(不以 "--" 开头的参数)@Overridepublic List<String> getNonOptionArgs() {return this.source.getNonOptionArgs();}// 内部类,用于处理和解析命令行参数// 继承自 SimpleCommandLinePropertySource,可以获取选项参数和非选项参数private static class Source extends SimpleCommandLinePropertySource {// 使用参数数组初始化 SourceSource(String[] args) {super(args);}// 获取所有非选项参数。@Overridepublic List<String> getNonOptionArgs() {return super.getNonOptionArgs();}// 获取指定名称的选项参数的值列表@Overridepublic List<String> getOptionValues(String name) {return super.getOptionValues(name);}}
}

四、Source

  Source是DefaultApplicationArguments解析参数内部的真正实现类,类图如下,逐一分析。

在这里插入图片描述

1、属性源PropertySource

  PropertySource是Spring框架中的一个核心抽象类,用于表示属性(键值对)的来源。通过将各种配置来源(如系统属性环境变量配置文件等)封装为PropertySource对象,Spring可以提供统一的接口来读取和管理这些配置数据。

  • 属性源名称:每个PropertySource实例都具有唯一的名称,用于区分不同的属性源
  • 属性源对象PropertySource<T>是一个泛型类,其中T代表具体的属性源类型
  • getProperty(String name):用于在属性源对象中检索具体的属性,name表示具体属性的键,返回具体属性的值
public abstract class PropertySource<T> {protected final Log logger = LogFactory.getLog(getClass());protected final String name;  // 属性源的名称protected final T source;  // 属性源的数据源对象// 使用给定的名称和源对象创建属性源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;}// 使用给定的名称和一个新的Object对象作为底层源创建属性源public PropertySource(String name) {this(name, (T) new Object());}// 返回属性源名称public String getName() {return this.name;}// 返回属性源的底层源对象。public T getSource() {return this.source;}// 判断属性源是否包含给定名称的属性(子类可以实现更高效的算法)// containsProperty和getProperty参数的name与上面定义的属性源名称的name不是一回事public boolean containsProperty(String name) {return (getProperty(name) != null);}// 返回与给定名称关联的属性值,如果找不到则返回null,子类实现@Nullablepublic abstract Object getProperty(String name);...
}

2、枚举属性源EnumerablePropertySource

  EnumerablePropertySource继承自PropertySource,主要用于定义getPropertyNames()方法,可以获取属性源对象中所有属性键的名称

public abstract class EnumerablePropertySource<T> extends PropertySource<T> {// 使用给定的名称和源对象创建属性源(调用父类PropertySource的构造方法)public EnumerablePropertySource(String name, T source) {super(name, source);}// 也是调用父类构造protected EnumerablePropertySource(String name) {super(name);}// 判断属性源是否包含具有给定名称的属性(重新了PropertySource的此方法)@Overridepublic boolean containsProperty(String name) {return ObjectUtils.containsElement(getPropertyNames(), name);}// 返回所有属性的名称public abstract String[] getPropertyNames();
}

3、命令行属性源CommandLinePropertySource

  CommandLinePropertySource是Spring框架中用于处理命令行参数PropertySource实现。它可以将应用程序启动时传入的命令行参数解析成键值对,便于在应用配置中使用。

  • 命令行属性源名称默认为commandLineArgs
  • getOptionValues(String name):通过命令行属性源(即选项参数键值对)的键获取对应的值
  • getNonOptionArgs():通过命令行属性源(即键默认为nonOptionArgs的非选项参数键值对)获取对于的值
  • 例:java -jar your-app.jar --server.port=8081 --spring.profiles.active=prod arg1 arg2
    • 选项参数会有多个键值对,key1为server.port,key2为spring.profiles.active
    • 非选项参数永远只有一个键值对,所有key都是nonOptionArgs
public abstract class CommandLinePropertySource<T> extends EnumerablePropertySource<T> {// CommandLinePropertySource实例的默认名称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);}// 可以通过set方法设置非选项参数的键的名称public void setNonOptionArgsPropertyName(String nonOptionArgsPropertyName) {this.nonOptionArgsPropertyName = nonOptionArgsPropertyName;}// 首先检查指定的名称是否是特殊的“非选项参数”属性,// 如果是,则委托给抽象方法#getNonOptionArgs()// 否则,委托并返回抽象方法#containsOption(String)@Overridepublic final boolean containsProperty(String name) {if (this.nonOptionArgsPropertyName.equals(name)) {return !getNonOptionArgs().isEmpty();}return this.containsOption(name);}// 首先检查指定的名称是否是特殊的“非选项参数”属性,// 如果是,则委托给抽象方法#getNonOptionArgs(),返回用逗号隔开字符串// 否则,委托并返回抽象方法#getOptionValues(name),返回用逗号隔开字符串@Override@Nullablepublic final String getProperty(String name) {if (this.nonOptionArgsPropertyName.equals(name)) {Collection<String> nonOptionArguments = getNonOptionArgs();if (nonOptionArguments.isEmpty()) {return null;}else {return StringUtils.collectionToCommaDelimitedString(nonOptionArguments);}}Collection<String> optionValues = getOptionValues(name);if (optionValues == null) {return null;}else {return StringUtils.collectionToCommaDelimitedString(optionValues);}}// 返回从命令行解析的选项参数集合中是否包含具有给定名称的选项protected abstract boolean containsOption(String name);// 返回与给定名称的选项参数关联的值集合@Nullableprotected abstract List<String> getOptionValues(String name);// 返回从命令行解析的非选项参数集合,永不为nullprotected abstract List<String> getNonOptionArgs();
}

4、简单命令行属性源SimpleCommandLinePropertySource

  SimpleCommandLinePropertySource是Spring框架中的一个类,继承自CommandLinePropertySource,用于解析和处理命令行参数。它设计为简单易用,通过接收一个字符串数组(即命令行参数 args),将参数分为"选项参数""非选项参数"两类。

  • 命令行属性源对象类型为CommandLineArgs,通过new SimpleCommandLineArgsParser().parse(args)获取
public class SimpleCommandLinePropertySource extends CommandLinePropertySource<CommandLineArgs> {// 构造函数:创建一个使用默认名称commandLineArgs的SimpleCommandLinePropertySource实例的命令行属性源public SimpleCommandLinePropertySource(String... args) {super(new SimpleCommandLineArgsParser().parse(args));}// 创建指定名称命令行属性源public SimpleCommandLinePropertySource(String name, String[] args) {super(name, new SimpleCommandLineArgsParser().parse(args));}// 获取所有选项参数的名称@Overridepublic String[] getPropertyNames() {return StringUtils.toStringArray(this.source.getOptionNames());}// 检查是否包含指定名称的选项@Overrideprotected boolean containsOption(String name) {return this.source.containsOption(name);}// 获取指定选项名称的值列表@Override@Nullableprotected List<String> getOptionValues(String name) {return this.source.getOptionValues(name);}// 获取所有非选项参数的列表@Overrideprotected List<String> getNonOptionArgs() {return this.source.getNonOptionArgs();}
}

五、解析参数原理

  在上一节中,我们了解了应用程序参数args被解析后的结构存储方式。接下来,我们回到文章开头,详细解析参数是如何被逐步解析出来的。

// 3.解析应用参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
  • 根据new DefaultApplicationArguments(args)寻找解析arg的位置

在这里插入图片描述

  • 解析完arg调用父类CommandLinePropertySource的构造方法

在这里插入图片描述

1、解析方法

  SimpleCommandLineArgsParser通过遍历传入的命令行参数数组,根据参数的格式,将参数解析并分为选项参数和非选项参数。

  • 选项参数解析规则
    • 选项参数必须以--前缀开头,例如 --name=John 或 --debug
    • 如果包含等号 =,= 左边的部分是选项名称,右边的部分是选项值
    • 如果没有等号,则视为不带值的选项
    • 如果获取不到选项名称(例如传入 --=value或–),抛出异常,表示参数格式无效
  • 非选项参数解析规则
    • 所有不以--开头的参数被视为非选项参数
class SimpleCommandLineArgsParser {public CommandLineArgs parse(String... args) {// 创建 CommandLineArgs 实例,用于存储解析结果CommandLineArgs commandLineArgs = new CommandLineArgs(); for (String arg : args) { // 遍历每个命令行参数if (arg.startsWith("--")) { // 如果参数以 "--" 开头,则视为选项参数String optionText = arg.substring(2); // 去掉 "--" 前缀String optionName; // 选项名称String optionValue = null; // 选项值,默认为 nullint indexOfEqualsSign = optionText.indexOf('='); // 查找等号的位置if (indexOfEqualsSign > -1) { // 如果找到了等号optionName = optionText.substring(0, indexOfEqualsSign); // 等号前的部分为选项名称optionValue = optionText.substring(indexOfEqualsSign + 1); // 等号后的部分为选项值}else {optionName = optionText; // 如果没有等号,整个文本为选项名称,值为 null}// 如果选项名称为空,抛出异常,例如,只输入了 "--=" 或 "--"if (optionName.isEmpty()) { throw new IllegalArgumentException("Invalid argument syntax: " + arg);}// 将解析出的选项名称和值添加到 CommandLineArgs 对象中commandLineArgs.addOptionArg(optionName, optionValue); }else {// 如果参数不是选项参数,直接作为非选项参数添加到 CommandLineArgs 对象中commandLineArgs.addNonOptionArg(arg); }}return commandLineArgs; // 返回解析结果}
}
  • 属性源对象类型CommandLineArgs
// 命令行参数的简单表示形式,分为“带选项参数”和“无选项参数”。
class CommandLineArgs {// 存储带选项的参数,每个选项可以有一个或多个值private final Map<String, List<String>> optionArgs = new HashMap<>();// 存储无选项的参数private final List<String> nonOptionArgs = new ArrayList<>();// 为指定的选项名称添加一个选项参数,并将给定的值添加到与此选项关联的值列表中(可能有零个或多个)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);}}// 返回命令行中所有带选项的参数名称集合public Set<String> getOptionNames() {return Collections.unmodifiableSet(this.optionArgs.keySet());}// 判断命令行中是否包含指定名称的选项。public boolean containsOption(String optionName) {return this.optionArgs.containsKey(optionName);}// 返回与给定选项关联的值列表。// 表示null表示该选项不存在;空列表表示该选项没有关联值。@Nullablepublic List<String> getOptionValues(String optionName) {return this.optionArgs.get(optionName);}// 将给定的值添加到无选项参数列表中public void addNonOptionArg(String value) {this.nonOptionArgs.add(value);}// 返回命令行中指定的无选项参数列表public List<String> getNonOptionArgs() {return Collections.unmodifiableList(this.nonOptionArgs);}
}

2、解析参数的存储和访问

  解析方法很简单,所有内容都在SimpleCommandLineArgsParser的parse方法中完成。相比之下,存储访问方式更为复杂。


  存储位置位于属性源对象PropertySource中。从代码可知,args表示命令行参数,因此属性源名称为命令行属性源默认名称commandLineArgs属性源对象为解析args后的键值对

在这里插入图片描述


  访问查询方式的底层实现就是操作CommandLineArgs中的optionArgs(选项参数)nonOptionArgs(非选项参数)两个集合,但此过程经过多次跳转,最终依次通过 DefaultApplicationArguments -> DefaultApplicationArguments#Source -> SimpleCommandLinePropertySource -> CommandLineArgs获取,其中CommandLineArgs就是是命令行属性源对象。这种设计主要是为了提供更灵活、安全的访问方式,避免直接暴露内部数据结构带来的潜在风险。

在这里插入图片描述

在这里插入图片描述

3、实际应用

  之前在SpringBoot基础(二):配置文件详解文章中有介绍过配置文件设置临时属性,这次回过头再来看,就很清晰明了了。

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

总结

  • 在SpringBoot启动时,启动类main函数中的args参数被解析为两类
    • 选项参数(如 --server.port=8080)
    • 非选项参数(如 arg1、arg2)
  • 对外暴露应用参数对象ApplicationArguments提供查询方法
    • getOptionValues(String name)方法可以获取选项参数
    • getNonOptionArgs() 方法则用于获取非选项参数
    • 这些参数在启动过程的后续阶段可供使用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/473895.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ZSTD 内存泄漏问题

优质博文&#xff1a;IT-BLOG-CN Zstandard&#xff08;简称zstd&#xff09;是一种无损压缩算法&#xff0c;由Facebook开发并开源。它旨在提供高压缩比和高解压速度的平衡&#xff0c;适用于多种数据压缩需求。 特点 【1】高压缩比&#xff1a; zstd能够在保持较高压缩比的…

前端:HTML (学习笔记)【1】

一&#xff0c;网络编程的三大基石 1&#xff0c;URL &#xff08;1&#xff09;url —— 统一资源定位符&#xff1a; 网址——整个互联网中可以唯一且准确的确定一个资源的位置。 【项目外】 网址——https://www.baidu.com/ …

【C++动态规划】3148. 矩阵中的最大得分|1819

本文涉及知识点 C动态规划 LeetCode 3148. 矩阵中的最大得分 给你一个由 正整数 组成、大小为 m x n 的矩阵 grid。你可以从矩阵中的任一单元格移动到另一个位于正下方或正右侧的任意单元格&#xff08;不必相邻&#xff09;。从值为 c1 的单元格移动到值为 c2 的单元格的得…

STM32完全学习——使用标准库点亮LED

一、使用标准库建立工程 &#xff08;1&#xff09;首先我们在ST的网站上面&#xff0c;下载标准库 &#xff08;2&#xff09;将标准外设库加入到项目中 我们一般只会使用到红色标注的那个文件夹&#xff0c;我们一般也只会将这个文件夹导入到工程里面&#xff0c;其他的还有…

解决微信小程序自定义tabbar点击两次才能跳转

在每个页面的js文件下加上此代码&#xff0c;selected属性代表每一个页面的下标&#xff0c;在不同的js文件下&#xff0c;要对应不同的selected值 代码&#xff1a; onShow() { // 确保 TabBar 存在并且设置选中项 if (this.getTabBar && this.getTabBar()) { this.…

学习threejs,使用AnimationMixer实现变形动画

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️THREE.AnimationMixer 动画…

Solana应用开发常见技术栈

编程语言 Rust Rust是Solana开发中非常重要的编程语言。它具有高性能、内存安全的特点。在Solana智能合约开发中&#xff0c;Rust可以用于编写高效的合约代码。例如&#xff0c;Rust的所有权系统可以帮助开发者避免常见的内存错误&#xff0c;如悬空指针和数据竞争。通过合理利…

【汇编语言】数据处理的两个基本问题(二) —— 解密汇编语言:数据长度与寻址方式的综合应用

文章目录 前言1. 指令要处理的数据有多长&#xff1f;1.1 通过寄存器指明数据的尺寸1.1.1 字操作1.1.2 字节操作 1.2 用操作符X ptr指明内存单元的长度1.2.1 访问字单元1.2.2 访问字节单元1.2.3 为什么要用操作符X ptr指明 1.3 其他方法 2. 寻址方式的综合应用2.1 问题背景&…

【算法】【优选算法】前缀和(下)

目录 一、560.和为K的⼦数组1.1 前缀和1.2 暴力枚举 二、974.和可被K整除的⼦数组2.1 前缀和2.2 暴力枚举 三、525.连续数组3.1 前缀和3.2 暴力枚举 四、1314.矩阵区域和4.1 前缀和4.2 暴力枚举 一、560.和为K的⼦数组 题目链接&#xff1a;560.和为K的⼦数组 题目描述&#x…

分布式cap理论学习

【分布式】CAP理论详解 一致性(Consistency) 代表数据在任何时刻&#xff0c;任何分布式节点&#xff0c;看到的都是符合预期的。有点类似于幂等&#xff0c;无论访问哪个节点&#xff0c;得到结果数据一致。 可用性(Availability) 强调的是任意时刻一定能读到数据&#xff…

主机型入侵检测系统(HIDS)——Elkeid在Centos7的保姆级安装部署教程

一、HIDS简介 主机型入侵检测系统(Host-based Intrusion Detection System 简称:HIDS);HIDS作为主机的监视器和分析器,主要是专注于主机系统内部(监视系统全部或部分的动态的行为以及整个系统的状态)。 HIDS使用传统的C/S架构,只需要在监测端安装agent即可,且使用用户…

Python蓝桥杯刷题1

1.确定字符串是否包含唯一字符 题解&#xff1a;调用count函数计算每一个字符出现的次数&#xff0c;如果不等于1就输出no&#xff0c;并且结束循环&#xff0c;如果等于1就一直循环直到计算到最后一个字符&#xff0c;若最后一个字符也满足条件&#xff0c;则输出yes import…

【ARM】MDK在debug模式下的Registers窗口包含哪些内容

【更多软件使用问题请点击亿道电子官方网站】 1、 文档目标 解决客户对于Debug模式下&#xff0c;对于Registers窗口包含的内容了解。 2、 问题场景 Registers窗口是在进入到debug模式下后&#xff0c;就会出现一个窗口。窗口中包含了很多寄存器信息。但是对于具体内容不了解…

河道无人机雷达测流监测系统由哪几部分组成?

在现代水利管理中&#xff0c;河道无人机雷达监测系统正逐渐成为一种重要的工具&#xff0c;为河道的安全和管理提供了强大的技术支持。那么&#xff0c;这个先进的监测系统究竟由哪几部分组成呢&#xff1f; 河道无人机雷达监测系统工作原理 雷达传感器通过发射电磁波或激光束…

浅谈数据仓库的架构及其演变

一、数据仓库分层架构 数据仓库分层一般分为三层&#xff0c;分别为数据仓库ODS层&#xff08;数据进出口贴源层&#xff09;、CDM层&#xff08;数据公共层&#xff09;和ADS层&#xff08;数据应用层&#xff09;。 1. ODS层&#xff1a;这是数据仓库的最底层&#xff0c;直接…

event_base

build default event_base event_base_new()函数分配并且返回一个新的具有默认设置的event_base。函数会检测环境变量&#xff0c;返回一个到event_base的指针。如果发生错误&#xff0c;则返回NULL。选择各种方法时&#xff0c;函数会选择OS支持的最快方法。 event_base_new…

PyTorch使用教程-深度学习框架

PyTorch使用教程-深度学习框架 1. PyTorch简介 1.1-什么是PyTorch ​ PyTorch是一个广泛使用的开源机器学习框架&#xff0c;特别适合深度学习的应用。它以其动态计算图而闻名&#xff0c;允许在运行时修改模型&#xff0c;使得实验和调试更加灵活。PyTorch提供了强大的GPU加…

数据科学与SQL:如何计算排列熵?| 基于SQL实现

目录 0 引言 1 排列熵的计算原理 2 数据准备 3 问题分析 4 小结 0 引言 把“熵”应用在系统论中的信息管理方法称为熵方法。熵越大&#xff0c;说明系统越混乱&#xff0c;携带的信息越少&#xff1b;熵越小&#xff0c;说明系统越有序&#xff0c;携带的信息越多。在传感…

28.<Spring博客系统⑤(部署的整个过程(CentOS))>

引入依赖 Spring-boot-maven-plugin 用maven进行打包的时候必须用到这个插件。看看自己pom.xml中有没有这个插件 并且看看配置正确不正常。 注&#xff1a;我们这个项目打的jar包在30MB左右。 <plugin><groupId>org.springframework.boot</groupId><artif…

无人机在森林中的应用!

一、森林资源调查 无人机可以利用遥感技术快速获取所需区域高精度的空间遥感信息&#xff0c;对森林图斑进行精确区划。相较于传统手段&#xff0c;无人机调查具有低成本、高效率、高时效的特点&#xff0c;尤其在地理环境条件不好的区域&#xff0c;调查人员无法或难以到达的…