SpringBoot自定义starter(starter的命名规范、starter的结构、自定义starter、为配置属性添加描述信息、检验配置属性)

news2024/12/22 19:15:03

文章目录

  • 0. 前言
  • 1. 前置知识
    • 1.1 starter的命名规范
    • 1.2 分析 Mybatis 的场景启动器
    • 1.3 starter的结构分析
  • 2. 创建自定义的场景启动器
    • 2.1 创建父工程
    • 2.2 初始化父工程
    • 2.3 创建 autoconfigure 模块
    • 2.4 创建 starter 模块
    • 2.5 在 starter 模块中引入 autoconfigure 模块的依赖
    • 2.6 新建配置类
    • 2.7 新建配置属性类
    • 2.8 让用户在配置文件中填写配置属性时有提示
    • 2.9 让用户在填写某个属性时只能选择给定的类型
    • 2.10 让自动配置类在某个类存在的情况下才生效
    • 2.11 打包
  • 3. 测试自定义starter
    • 3.1 创建测试工程
    • 3.2 引入 starter 的依赖
    • 3.3 编写配置文件
    • 3.4 编写测试类
  • 4. 为配置属性添加描述信息
  • 5. 在配置文件中显示属性的默认值
  • 6. 控制配置类在某个配置属性存在的情况下才进行加载
  • 7. 校验配置属性
  • 8. 补充:spring.factories 文件
  • 9. 温馨提示

0. 前言

SpringBoot 能够开箱即用,归功于一个一个的 starter(场景启动器),SpringBoot 把我们常用的场景抽取成了一个个starter(场景启动器),我们通过引入 SpringBoot 提供的场景启动器,再进行少量的配置就能使用相应的功能

但是 SpringBoot 并不能囊括我们所有的使用场景,我们可以自定义 starter 来满足我们的业务场景

1. 前置知识

1.1 starter的命名规范

Spring 官方提供的 starter 一般是以 spring-boot-starter 开头的,而第三方 starter 一般是以产品名字开头的

在这里插入图片描述

以 Mybatis 的场景启动器为例,Spring 官方并没有提供 Mybatis 的场景启动器,那我们平时用的 Mybatis 场景启动器是从哪里来的?当然是 Mybatis 官方自己提供的,这么一想,Mybatis 官方还是挺贴心的


如果项目中有一个比较好用的模块,我们想让这个模块应用在别的 SpringBoot 项目中,并且可以开箱即用,我们就可以自定义一个 starter

自定义 starter 是一项偏向于架构方面的工作,如果你平时是一个只会 CRUD 的程序员,大概率是接触不到的

既然 MyBatis 的场景启动器是 MyBatis 官方提供的,而且能被 Spring 官方认可,那我们就仿照 Mybatis 的场景启动器来编写我们自己的场景启动器

1.2 分析 Mybatis 的场景启动器

我们找到 Mybatis 的自动配置类

在这里插入图片描述

以下是 MybatisAutoConfiguration 类的摘录以及各个属性的解释

在这里插入图片描述

// 表示这个类是一个配置类,用于定义Bean,proxyBeanMethods设为false表示不需要代理Bean方法,可以提高启动性能
@Configuration(
        proxyBeanMethods = false
)

// 这个配置类只有在类路径下存在SqlSessionFactory和SqlSessionFactoryBean这两个类时才会被加载
@ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class})

// 这个配置类只有在容器中存在且只存在一个DataSource Bean时才会被加载
@ConditionalOnSingleCandidate(DataSource.class)

// 启用对MybatisProperties类的配置属性的支持,这样就可以在application.properties或application.yml文件中配置Mybatis的属性
@EnableConfigurationProperties({MybatisProperties.class})

// 表示这个配置类应该在DataSourceAutoConfiguration和MybatisLanguageDriverAutoConfiguration配置之后自动配置
@AutoConfigureAfter({DataSourceAutoConfiguration.class, MybatisLanguageDriverAutoConfiguration.class})

public class MybatisAutoConfiguration implements InitializingBean {

    private static final Logger logger = LoggerFactory.getLogger(MybatisAutoConfiguration.class);

    private final MybatisProperties properties;

    private final Interceptor[] interceptors;
    // Mybatis拦截器数组,用于在Mybatis操作过程中进行拦截处理

    private final TypeHandler[] typeHandlers;
    // Mybatis类型处理器数组,用于处理Java类型与数据库类型之间的转换

    private final LanguageDriver[] languageDrivers;
    // Mybatis语言驱动数组,用于解析Mybatis的动态SQL

    private final ResourceLoader resourceLoader;
    // Spring资源加载器,用于加载资源文件

    private final DatabaseIdProvider databaseIdProvider;
    // 数据库ID提供者,用于提供数据库产品名称,以区分不同的数据库

    private final List<ConfigurationCustomizer> configurationCustomizers;
    // Mybatis配置自定义器列表,用于自定义Mybatis配置

    private final List<SqlSessionFactoryBeanCustomizer> sqlSessionFactoryBeanCustomizers;
    // SqlSessionFactoryBean自定义器列表,用于自定义SqlSessionFactoryBean的创建过程
    
}

仅仅编写自动配置类是不够的,我们还需要在 resources 目录的 META-INF/spring 目录下添加 org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件

在这里插入图片描述

Mybatis 提供的 org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件的内容如下

org.mybatis.spring.boot.autoconfigure.MybatisLanguageDriverAutoConfiguration
org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration

Spring 会扫描 org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件中的所有组件,再将组件注入到容器中,我们自定义的配置类就会起作用了

1.3 starter的结构分析

如何自定义 starter,也是有讲究的,Spring 官方建议我们使用 starter + autoconfigure 来自定义 starter

在这里插入图片描述

starter + autoconfigure 是标准的场景启动器结构,其实 starter 模块里面没有什么内容,起核心作用的是 starter 模块中的 pom.xml 文件

在这里插入图片描述

starter 的 pom.xml 文件中依赖了 autoconfigure,并且依赖了其它 jar 包(可以看到,Mybatis 的底层还是基于 JDBC 实现的)

  • starter 模块相当于一个空的 jar 文件,仅仅提供辅助管理依赖的功能
  • autoconfigure 模块只需要专注于实现自动配置类的逻辑

在这里插入图片描述

用户如果要使用场景启动器,只需要引入 starter 部分,因为 starter 部分会自动地帮我们引入 autoconfigure 部分


当然,starter + autoconfigure 只是 Spring 官方提供的一个规范,不一定要遵守,例如阿里巴巴的 druid-spring-boot-starter 就比较任性,只有 starter 部分,在 starter 部分里面包含了 autoconfigure 部分

在这里插入图片描述

2. 创建自定义的场景启动器

接下来我们从头开始搭建自定义的 starter

如果你想让更多的人能够使用你的 starter,可以使用较低版本的 JDK 和较低版本的 SpringBoot 开发

2.1 创建父工程

我们创建一个新工程,作为父工程,管理 starter 模块和 autoconfigure 模块

在这里插入图片描述

不用勾选其它依赖

在这里插入图片描述

创建工程后先修改 Maven 仓库路径和 Maven 的配置文件

在这里插入图片描述

2.2 初始化父工程

父工程不需要 src 目录,我们删除父工程的 src 目录

在这里插入图片描述

接着在父工程的 pom.xml 文件的 properties 标签中添加以下内容,表明父工程是一个聚合工程

在这里插入图片描述

<packaging>pom</packaging>

最后把 <build></build> 标签也删掉,因为父工程并不需要打包插件

2.3 创建 autoconfigure 模块

因为 starter 模块依赖 autoconfigure 模块,所以我们先创建 autoconfigure 模块

右键父工程

在这里插入图片描述

选择普通的 Maven 项目,因为用 SpringBoot 模版我们还需要手动删除一些不必要的依赖

在这里插入图片描述

2.4 创建 starter 模块

在这里插入图片描述

2.5 在 starter 模块中引入 autoconfigure 模块的依赖

在 starter 模块的 pom.xml 文件中引入 autoconfigure 模块的依赖

<dependencies>
    <dependency>
        <groupId>cn.edu.scau</groupId>
        <artifactId>scau-spring-boot-autoconfigure</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>

    <!--如果当前starter需要依赖其它的starter或jar包,在这里导入-->
</dependencies>

2.6 新建配置类

在 autoconfigure 模块下新建一个配置类,配置类的命名规范为 XXXAutoConfiguration

package cn.edu.scau;

import org.springframework.context.annotation.Configuration;

@Configuration
public class MyPrinterAutoConfiguration {

}

2.7 新建配置属性类

在 autoconfigure 模块下新建一个 MyPrinterProperties 配置属性类

package cn.edu.scau;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "my.printer")
public class MyPrinterProperties {

}

prefix = “my.printer” 指的是在配置文件中填写配置属性时的前缀

2.8 让用户在配置文件中填写配置属性时有提示

为了在 application.yml 文件或 application.properties 文件中填写配置属性时有提示,我们需要完成两个步骤

第一步:在 autoconfigure 模块中添加文件处理器的依赖

<!--导入配置文件处理器,配置文件进行绑定就会有提示-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
</dependency>

第二步:在 autoconfigure 模块的 META-INF/spring 目录下创建 org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件

org.springframework.boot.autoconfigure.AutoConfiguration.imports

文件内容如下

cn.edu.scau.MyPrinterAutoConfiguration

完成上述两个步骤后,MyPrinterProperties 类的 @ConfigurationProperties 可能会给出警告信息,因为 MyPrinterProperties 是一个配置属性类,但它并没有没有与任何一个由 Spring 管理的配置类绑定在一起

在这里插入图片描述

我们只需要将 MyPrinterAutoConfiguration 类与 ConfigurationProperties 类绑定在一起就可以了,可以通过 EnableConfigurationProperties 注解绑定

@EnableConfigurationProperties(MyPrinterProperties.class)

在这里插入图片描述

2.9 让用户在填写某个属性时只能选择给定的类型

我们来做一个小案例:自定义一个 MyPrinter 类,可以接收两种颜色(白色和红色,其实也就是 System.out 和 System.err),用户可以选择不同的颜色来打印,默认为白色


要实现让用户选择的效果,我们需要在 MyPrinterProperties 类中定义一个枚举类型,该枚举类型有 WHITE 和 RED 两种取值

package cn.edu.scau;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "my.printer")
public class MyPrinterProperties {

    /**
     * 颜色
     */
    private Color color = Color.WHITE;

    public void setColor(Color color) {
        this.color = color;
    }

    public Color getColor() {
        return color;
    }

    public enum Color {
        WHITE("white"),
        RED("red");

        private String value;

        Color(String color) {
            this.value = color;
        }

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }
    }

}

接着在 MyPrinter 类中添加带有 MyPrinterProperties 配置属性类的构造函数

package cn.edu.scau;

public class MyPrinter {

    private final MyPrinterProperties myPrinterProperties;

    public MyPrinter(MyPrinterProperties myPrinterProperties) {
        this.myPrinterProperties = myPrinterProperties;
    }

    public void print(String message) {
        MyPrinterProperties.Color color = myPrinterProperties.getColor();
        if (MyPrinterProperties.Color.WHITE.equals(color)) {
            System.out.println(message);
        } else if (MyPrinterProperties.Color.RED.equals(color)) {
            System.err.println(message);
        }
    }

}

最后在 MyPrinterAutoConfiguration 类中添加带有 MyPrinterProperties 配置属性类的构造函数(也可以使用 Autowired 注解注入,但使用构造器注入更加规范)

一般我们是将要封装的类放在自动配置类中通过 @Bean 注解放入到 Spring 容器中,这样 org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件就只需要引入自动配置类

在这里插入图片描述

2.10 让自动配置类在某个类存在的情况下才生效

我们可以在配置类中指定在某个某个类存在的情况下才生效

在这里插入图片描述

@ConditionalOnClass(MyPrinter.class)

2.11 打包

在 Maven 中的父工程的生命周期中找到 install,将自定义 starter 打包到本地(deploy 选项用于正式发布到中央 Maven 仓库中)

在这里插入图片描述

3. 测试自定义starter

3.1 创建测试工程

我们在 IDEA 中新创建一个 SpringBoot 项目,测试自定义 starter 是否有用

在这里插入图片描述

在这里插入图片描述

接着修改 Maven 仓库路径和 Maven 的配置文件

3.2 引入 starter 的依赖

<dependency>
    <groupId>cn.edu.scau</groupId>
    <artifactId>scau-spring-boot-starter</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>

starter 的名字要与你在 starter 模块中对应的 artifactId 对应

在这里插入图片描述

3.3 编写配置文件

编写测试工程的配置文件(application.yml)

在这里插入图片描述

在这里插入图片描述

my:
  printer:
    color: white

可以看到,编写配置文件时有提示了,而且只能从我们给定的两个值里面进行挑选


如果强行填写其它值,IDEA 会给出警告信息

在这里插入图片描述

3.4 编写测试类

我们新建一个测试类,测试 MyPrinter 类是否正常能正常运行

package com.edu.scau;

import cn.edu.scau.MyPrinter;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class TestCustomStarterApplicationTests {

    @Autowired
    private MyPrinter myPrinter;

    @Test
    void contextLoads() {
        myPrinter.print("聂可以");
    }

}

将配置文件中的 color 属性改为 white,可以成功打印信息

在这里插入图片描述


将配置文件中的 color 属性改为 red,也能正确地切换

在这里插入图片描述


如果不指定 color 属性,也能成功打印,因为如果用户不指定,默认使用的就是 white,这就是 SpringBoot 中约定大于配置的由来,给属性设定一个默认值,用户需要修改的时候手动修改即可

4. 为配置属性添加描述信息

我们在指定 Web 容器的占用端口时,发现 port 属性有对应的描述,这是怎么做到的呢

在这里插入图片描述

我们只需要在属性的上方添加文档注解,这些文档注解在打包后会解析到 target/classes/META-INF/spring-configuration-metadata.json 文件中

在配置文件中填写配置属性时能够有描述信息,就是 spring-configuration-metadata.json 文件起的作用

spring-configuration-metadata.json

在这里插入图片描述

可以看到,添加文档注释后,color 属性也有描述了(当然,更规范的是使用中文的描述)

在这里插入图片描述

5. 在配置文件中显示属性的默认值

如果某个在属性一开始就给定了一个值,那么这个值就是默认值,但是我们定义的 color 是一个枚举类型,可能 IDEA 的显示默认的枚举类型功能做得还不是很完善,我们可以添加一个 String 类型的属性来测试一下

注意:要为属性添加 getter 和 setter,不然 Spring 会认为该属性不是配置属性,进而忽略掉该属性

在这里插入图片描述

我们重新打包后,在测试工程填写配置文件,发现 message 属性的默认值已经能够正确显示出来了

在这里插入图片描述

当然,起核心作用的还是 META-INF/spring-configuration-metadata.json 文件

在这里插入图片描述

6. 控制配置类在某个配置属性存在的情况下才进行加载

我们可以在配置类上添加 @ConditionalOnProperty 注解,控制配置类在某个配置属性存在的情况下才进行(不一定是配置类,只要是交由 Spring 管理的类或方法返回值,都可以添加该注解)

  • 只有用户在配置文件中填写了这个属性,才会将配置类加载进 Spring 容器,即使 message 属性有默认值
  • 就算用户填写这个属性时填写的是一个空值,@ConditionalOnProperty 注解也会生效,换句话说,只要这个属性在配置类文件出现过,@ConditionalOnProperty 注解就会生效
@ConditionalOnProperty(prefix = "my.printer", name = {"message"})

在这里插入图片描述

7. 校验配置属性

我们可以规定用户在填写某个配置属性时要满足指定的要求,具体的做法是让自动配置类实现 InitializingBean 接口,重写 afterPropertiesSet 方法,在 afterPropertiesSet 方法里面编写我们的校验逻辑

当然,更好的做法是自定义一个校验类,通过构造器将配置属性类传入校验类中,让检验类实现 InitializingBean 接口,在校验类中编写检验的逻辑(比较规范的做法是在自动配置类中添加一个方法,该方法的返回值是检验类,然后通过 @Bean 注解将校验类注入到容器中,具体可参考 MyPrinter 类)

在这里插入图片描述

@Override
public void afterPropertiesSet() {
    if (myPrinterProperties.getMessage().isEmpty()) {
        throw new IllegalArgumentException("Message can not be empty");
    }
}

重写打包后,在测试工程中测试,发现程序报错了,并且也给出了响应的警告信息

在这里插入图片描述

8. 补充:spring.factories 文件

  • spring.factories文件已在 SpringBoot 2.7.x 废止,在 SpringBoot 3.x 中全面移除
  • spring.factories 文件存放在 resources 目录的 META-INF 目录下

9. 温馨提示

如果修改 starter 的内容后其它项目中没有立即生效,是因为没有重新打包(先 clean,再 install)

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

算法学习:滑动窗口

题目 滑动窗口 滑动窗口的题目在解决统计连续带特殊要求的元素串问题时作用巨大。逃离仅仅只是套路学习的黑洞&#xff0c;我认为这种方法在无序的统计中&#xff0c;找到了有序的切入点。初看题目时&#xff0c;可以想到的统计方法有很多&#xff0c;但实现在计算机上则必须有…

我在高职教STM32——准备HAL库工程模板(1)

新学期开学在即,又要给学生上 STM32 嵌入式课程了。这课上了多年了,一直用的都是标准库来开发,已经驾轻就熟了。人就是这样,有了自己熟悉的舒适圈,就很难做出改变,老师上课也是如此,排斥新课和不熟悉的内容。显然,STM32 的开发,HAL 库已是主流,自己其实也在使用,只不…

Mac使用Elasticsearch

下载 Past Releases of Elastic Stack Software | Elastic 解压tar -xzvf elasticsearch-8.15.1-darwin-x86_64.tar.gz 修改配置文件config/elasticsearch.yml xpack.security.enabled: false xpack.security.http.ssl: enabled: false 切换目录 cd elasticsearch-8.15.1/…

Superset二次开发之Select 筛选器源码分析

路径&#xff1a;superset-frontend/src/filters/components/Select 源码文件&#xff1a; 功能点&#xff1a; 作用 交互 功能 index.ts作为模块的入口点,导出其他文件中定义的主要组件和函数。它使其他文件中的导出可以被外部模块使用。 SelectFilterPlugin.tsx 定义主要…

Qt/C++ 个人开源项目#串口助手(源码与发布链接)

一、项目概述 该串口助手工具基于Qt/C开发&#xff0c;专为简化串口通信调试与开发而设计&#xff0c;适合新手快速上手。工具具有直观的用户界面和丰富的功能&#xff0c;旨在帮助用户与串口设备建立可靠通信&#xff0c;便于调试、数据传输和分析。 二、主要功能 波特率&a…

Qt QLineEdit 输入内容后字数在右侧动态展示

前言 QLineEdit 设置可输入最大长度可以使用 lineEdit->setMaxLength(10); 怎么实时的把当前输入字数显示出来呢&#xff0c;像饿了么的 input 组件那样 <el-inputtype"text"placeholder"请输入内容"v-model"text"maxlength"10&q…

基于orangePi的智能家居系统

目录 一.接线图 1.orangePi接线 2.继电器接线 二.语音模块的配置 1.pin脚的配置 2.命令词自定义信息 三.测试 1.通过gpio指令测试烟雾检测器是否正确连接 2.编写脚本测试其他模组接线是否正常 四.人脸识别方案 1.首先开通人脸搜索识别服务 2. 点击产品控制台,向人…

【重学 MySQL】十五、过滤数据

【重学 MySQL】十五、过滤数据 基本用法使用AND、OR和NOT使用IN操作符使用BETWEEN操作符使用LIKE操作符使用IS NULL和IS NOT NULL 在MySQL中&#xff0c;过滤数据主要通过WHERE子句来实现。WHERE子句允许你指定条件来过滤从表中检索出来的行。只有当行满足WHERE子句中的条件时&…

个人随想-一个有意思的鼠标截屏RAG

multi-model rag现在的技术已经比较成熟了&#xff0c;我们也落地了很多公司的rag和agent项目。今天先不说项目落地&#xff0c;今天给大家分享一个有意思的需求。 广州的一家公司&#xff0c;当我们rag搭建完成后&#xff0c;他们的一个产品经理提了一个需求。他们说&#xf…

C#转java工具

使用 激活 点击关闭即可 参考文献 https://www.cnblogs.com/liyhbk/p/17358520.html

【视频教程】手把手AppWizard轻松制作一个emWin滑动主界面控制框架,任意跳转控制(2024-09-06)

现在的新版AppWizard已经比较好用&#xff0c;用户可以轻松的创建各种项目常规界面。 比如早期创建一个支持滑动的主界面框架&#xff0c;并且可以跳转各种子界面&#xff0c;仅仅界面布局和各种图片格式转换都要花不少时间&#xff0c;而现在使用AppWizard&#xff0c;可以说…

关键点检测(7)——yolov8-head的搭建

前两节我学习了yolov8的backbone和head操作。这一节就到了head部分。  我们知道yolov8在流行的yolov5的架构上进行了扩展。在多个方面提供了改进。尤其是head部分&#xff0c;变化最大。yolov8模型与其前身的主要区别在于使用了无锚点检测&#xff08;即从原先的耦合头变成了解…

无人机电调接线

接线方式&#xff1a; 电调的作用是将飞控板的PWM控制信号转变为电流信号 因为电机的电流是很大的&#xff0c;通常每个点击正常工作时都平均有3A左右的电流&#xff0c;如果没有电调的存在&#xff0c;飞控无法承受这么大的电流。 电调的选择&#xff1a;电调上标的电流值是…

240907-Gradio渲染装饰器Render-Decorator

A. 最终效果 B. 示例代码 import gradio as gr import gradio as grwith gr.Blocks() as demo:input_text gr.Textbox()gr.render(inputsinput_text)def show_split(text):if len(text) 0:gr.Markdown("## No Input Provided")else:# for letter in text:for lett…

精通Java微服务

第1章 微服务是在面向服务架构SOA的基础上进一步发展而来的&#xff0c;它比SOA做得更加彻底&#xff0c;其单体服务被更加彻底地划分&#xff0c;最大限度地实现了服务的单一职责。 1.1.2互联网 即计算机网络&#xff0c;连接了世界上数以万计的计算机设备&#xff08;可联…

ROADM(可重构光分插复用器)-介绍

1. 引用 https://zhuanlan.zhihu.com/p/163369296 https://zhuanlan.zhihu.com/p/521352954 https://zhuanlan.zhihu.com/p/91103069 https://zhuanlan.zhihu.com/p/50610236 术语&#xff1a; 英文缩写描述灰光模块彩光模块CWDM&#xff1a;Coarse Wave-Length Division …

1233333333333

&#x1f4e2;博客主页&#xff1a;https://blog.csdn.net/2301_779549673 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01; &#x1f4e2;本文由 JohnKi 原创&#xff0c;首发于 CSDN&#x1f649; &#x1f4e2;未来很长&#…

【JVM】JVM栈帧中的动态链接 与 Java的面向对象特性--多态

栈帧 每一次方法调用都会有一个对应的栈帧被压入栈&#xff08;虚拟机栈&#xff09;中&#xff0c;每一个方法调用结束后&#xff0c;都会有一个栈帧被弹出。 每个栈帧中包括&#xff1a;局部变量表、操作数栈、动态链接、方法返回地址。 JavaGuide&#xff1a;Java内存区域…

STM32CubeMX和HAL库

目录 STM32CubeMX和HAL库介绍 STM32Cube主要包括两部分 安装MCU固件包 软件功能与基本使用 STM32CubeMX和HAL库介绍 STM32CubeMX软件是ST有限公司为STM32系列微控制器快速建立工程&#xff0c;并快速初始化使用到的外设、GPIO等而设计的&#xff0c;大大缩短了开发时间。 同…

【面试八股总结】MySQL日志:undo log、redo log、binlog

MySQL中存在三种日志&#xff1a; undo log&#xff08;回滚日志&#xff09;&#xff1a;是 Innodb 存储引擎层生成的日志&#xff0c;实现了事务中的原子性&#xff0c;主要用于事务回滚和 MVCC。redo log&#xff08;重做日志&#xff09;&#xff1a;是 Innodb 存储引擎层…