C语言基础 位域

news2024/9/21 8:02:03

C语言基础:位域

主题:位域(bit-field)
关键字:位域 冒号 结构体 存储空间
参考链接:C语言中文网:位域 、C菜鸟工具(在线编译器)、位域知乎问答
注:以下内容中如存在错误或缺漏,感谢评论指正,将尽快进行更正完善。


文章目录

  • C语言基础:位域
  • 一、位域是什么?
  • 二、为什么需要使用位域
    • 1. 减少数据存储空间
    • 2. 提高代码阅读性
  • 二、位域结构体成员的使用
    • 1.C 语言的位域结构体成员
    • 2.位域使用注意事项
    • 3.位域的存储
  • 总结



一、位域是什么?

struct
{
  unsigned int led_status     : 1; //led灯的开关状态,占1个bit
  unsigned int led_color      : 3; //led灯的颜色,占3个bit
  unsigned int led_luminance  : 4; //led灯的亮度等级,占4个bit
} status;

现实中的很多信息,例如设备的开关状态,并不需要占用一个完整的字节存储。为了更方便处理这类数据,C语言提供了一种数据结构类型,叫做“位域”,也叫“位段”。位域是一种结构体成员的类型,从字面意思理解,位域把一个存储单元,比如一个字节单元含8bit空间,按占用位bit大小划分出不同的区域,存放不同的数据。

bit76-43-0
位域成员存放数据1存放数据2存放数据3

二、为什么需要使用位域

1. 减少数据存储空间

为什么需要使用位存储?举个直观的例子:我们要控制2个彩色的灯,通过串口通信,给它下发控制指令,从而改变灯的开关状态和颜色状态。(表中data=0xda=0b11011010)
开关状态(占1位): 0=OFF ,1= ON
颜色状态(占3位): 0=红色,1=绿色,2=蓝色,3=黄色,4=紫色,5=白色。

字节存储方式(共4字节)byte1234
位域存储方式(共1字节)bit位76-432-0
数据定义灯a开关灯a颜色灯b开关灯b颜色
数据解释1=ON5=白色1=ON2=蓝色
data11011010

表中可以看出,通过位存储的方式,1个字节,就能实现2个灯的控制,而如果采用字节方式,控制2个灯需要4字节。假设要控制200个灯时,按位域方式进行的存储和通信,只需要100字节,而以字节方式则需要400字节。更少的通信数据,有利于保证通信效率,减少误码率,因此位域结构体在网络通信和CAN通信中较常见,有利于提高网络带宽利用率。
总结1:位域方式在数据存储中起到了减少存储空间的作用、在通信中起到减少通信数据量的作用。

2. 提高代码阅读性

接上面控制灯的例子,(表中data=0xda=0b11011010),现在要将灯a关闭,也就是第7bit置0,同时不能改变影响其他数据,也就是将数据变化为(data=0x5a=0b01011010)。虽然可以通过以下代码间接实现位域的赋值功能,但过程并不直观,代码理解起来费时。
总结2:使用位域结构体成员,有助于简化代码,使代码结构清晰

int main()
{
   #define LED_OFF  0
   unsigned char   led_data_init = 0b11011010;//灯总状态初始数据
   unsigned char   led_data = led_data_init;//灯总状态数据
	
   unsigned char   leda_status = LED_OFF;//灯a状态数据:关灯
   unsigned char   leda_status_bitsize = 1;  //灯a状态数据,占用led_data的1个bit
   unsigned char   leda_status_bitindex = 7; //灯a状态数据,存储在led_data的bit7位置(bit7-0)
	  	
   /**
   * 该宏函数得到一个将对应位域位置赋值0的值(bit7-0)
   * 例:0b0111 1111 = BIT_SEAT(1,7)
   * 例:0b0001 1111 = BIT_SEAT(3,5)
   */
   #define  BIT_SEAT(bit_size,bit_index)   (unsigned char)(~(~(0xff<< bit_size)<<bit_index))

   led_data &= BIT_SEAT(leda_status_bitsize,leda_status_bitindex);//led_data中对应域值清零
   led_data |= leda_status << 7;//led_data中对应域赋值新值
	
	//输出结果:led_data_init=0xda,led_data=0x5a	   
   printf("led_data_init=0x%x,led_data=0x%x",led_data_init,led_data);
   	
   return 0;
}

二、位域结构体成员的使用

1.C 语言的位域结构体成员

带有预定义宽度的变量被称为位域,位域在本质上就是一种结构类型,其成员按二进制位分配,它的基本用法与结构体一样。

struct 位域结构名 
{
	          
	类型说明符 type     位域名member_name :  位域长度 width ;
	类型说明符 type     位域名member_name :  位域长度 width ;
	......
	
}位域结构体定义的变量;

/**
* 以下代码定义了一个名为 struct bs 的结构体,
* data 为 bs 的结构体变量,共占四个字节:
*/
struct bs{
    int a:8; //变量a,占8bit
    int b:2; //变量b,占2bit
    int c:6; //变量c,占6bit
}data,*pdata;

pdata=&data;
data.b = 1;//位域的使用和结构成员的使用相同
pdata->c = 10;//位域结构体可以使用指针,位域成员不能使用指针。

2.位域使用注意事项

2.1.位域的类型
根据早期ANSI C规定,位域最开始只支持 int,unsigned int ,unsigned int三种类型,后面C99标准又增加了bool类型。但几乎所有的编译器都对此进行了进一步扩展,char ,unsigned char ,long,enum等都是可用的类型。实际应用中,尽量使用无符号类型,否则可能存在符号不一致问题。
位域不支持浮点型,否则编译提示:bit-field ‘c’ has invalid type。

2.2.位域的宽度
宽度必须小于或等于位域类型的位宽度,例如char类型,位宽度最大为8,int类型32位系统中,位宽度最大为32。错误的示例如下,编译器会提示错误:error: width of ‘a’ exceeds its type。

unsigned char  a:9; //错误的宽度定义,a最大为8。
unsigned int   b:33; //错误的宽度定义(假设在32位系统),32位系统中最大为32。

**注:**网上常见一种说法”位域不允许跨2字节,如一个字节所剩空间不够存放另一位域时,则会从下一单元起存放该位域,也就是说位域不能超过8bit。“这种说法并不正确,可能是英文翻译和理解错误。

比较恰当的说法是,**位域不允许跨2个类型单位,也就是说位域长度不能超过所依赖类型的最大位bit数。**例如,程序运行在32位系统,使用unsigned int,则位域宽度不能超过32。
使用以下例程序测试验证,刚好占32位,4个字节,位域数据紧密排列,并不存在一个字节所剩空间不够,从下一单元存放的现象。

struct bs{
    unsigned a:7;
    unsigned b:7;   
    unsigned c:7;    
    unsigned d:7;
    unsigned e:4;
    } n;
    //结果输出sizeof n = 4
   printf("sizeof n = %d\n",sizeof(n));

2.3.对位域结构体成员赋值不要超出其位域数值范围
在使用位域时,要特别注意检查数据赋值范围,虽然很基础但也最容易出错的操作,在进行位域成员赋值时,很可能不经意间就超出了范围。

struct
{
  unsigned int age : 3;//age 的赋值范围0-7
} Age;
 
int main( )
{
   Age.age = 8; // 二进制表示为 1000 有四位,超出
   printf( "Age.age : %d\n", Age.age ); 
   return 0;
}

位域成员赋值不要超过范围,以上代码编译时,会提示警告:第四位溢出,溢出的位会被忽略,只保留有效位,printf输出Age.age : 0

2.3无名位域、空域
位域可以是无名位域,也叫空域,这时它只用来作填充或调整位置。无名的位域是不能使用的。
无名位域的长度为0时,表示该单元后续空间都不能使用,需要从下一个新单元存储新数据。
已命名位域不能设置0长度(编译报错),位段定义的第一个位段长度不能为0(虽然编译不报错,但应避免这样使用)。

struct k{
    int a:1;
    int  :2;    /* 该 2 位不能使用 */
    int  :0;    /* 该int单元,后续位不能使用 */
    int b:2;    /* 存储在下一个新的int单元 */
};

2.4位域成员指针
C语言无法使用&对位域成员做取地址运算,不存在位域成员指针。


2.5位域数据的符号问题

在计算机中,所有的数据以补码的形式存储。使用有符号类型时,其最高位,会被作为符号位,数据以补码存储。
位域成员a,只有1位,0b1,最高位即本身,被当做符号位1。可以理解为向前补充符号位0xffffffff=-1,
位域成员b,有2位,0b11,最高位被当做符号位1,可以理解为向前补充符号位0xffffffff=-1。也可以通过补码转原码方式理解,补码的符号位1,数据为1,转换为原码,符号位1不变表示负号,数据为1,取反=0+1=1,整体表示-1。

正数补码等于原码,不存在符号变化,推荐位域中使用无符号类型。

{
struct bs{
    signed a:1;
    signed b:2;    
    } n ;
	
n.a=1;
n.b=3;

//打印输出a=-1,b=-1
printf ("a =%d, b=%d",n.a,n.b);
 

3.位域的存储

3.1位域数据的平台兼容性
位域天然的不利于兼容性。因为C语言标准并没有规定位域的具体存储方式,基于不同的编译器,不同的运行环境都可能有不同的实现。位域的数据存储,和编译器和运行环境有很大的关系,为了保证在不同平台运行结果的一致性,实现跨平台兼容。尽量使用无符号类型,并尽量简单的使用位域结构体成员。
如果位域在该项目中使用非常少,无关键用途,为了保证保证兼容性,可以选择不使用位域。

3.2类型相同的相邻位域数据存储

当相邻成员的类型相同时,位域按顺序优先存储在同一个单元中。
如果一个单元所剩空间不够存放另一位域时,则会从下一单元起存放该位域。如果剩余空间还够存放另一位域,那么后面的成员紧邻前一个成员存储,中间没有空隙。就像行李箱里放衣服一样,塞的下就继续放,塞不下就换下一个行李箱放。

struct bs{
 unsigned short a: 6;
 unsigned short b: 7;
 unsigned short c: 4;
 };

先定义的数据放在低位,单元1存完a、b后,剩余3bit空间放不下c,将c放到下一个单元中。
在这里插入图片描述
3.3不同类型的相邻位域数据存储问题
如果相邻位域字段的类型不同,则各编译器的具体实现不同。是否进行压缩,以及如何对齐都存在不确定性,建议编写例程,在具体环境下编译测试。

如果相邻位域字段的类型不相同,但数据长度相同,根据编译器不同,确定是否进行压缩,可能压缩。
如果相邻位域字段的类型不相同,但数据长度不同,根据编译器不同,确定是否进行压缩,通常不压缩。
如果相邻位域字段的类型不相同,总字节数为位域类型所占字节较大的整数倍,遵守结构体数据对齐规则。
如果位域中间穿插着非位域类型,则非位域数据,不参与压缩。可以简单理解为非位域类型,是独立的单元,本身已经占用了自身单元所有bit位置,没有空位给别的数据填充。

struct bs{
    unsigned a:7;
    unsigned b;//非位域数据,单独占一个unsigned int单元   
    unsigned c:1;    
    } n;

3.4位域数据的大小端存储及位序

数据的大小端及位序和编译器,处理器都有关系。
大小端是一种字节序,是指字节数据的外部排序方式,也就是多个btye数据在存储地址中的排序方式,单纯的大小端定义与字节内部存储无关。但通常,我们默认大端使用MSB,小端使用LSB,所以很多文章并不会特别指明位序,只提大小端,默认不提位序,导致对大小端的解释看起来有多个不同的版本。

模式应用
大端STM8,C51,TCP/IP协议
小端STM32,X86

ARM的大小端模式可配置,需要具体分析,最好运行测试代码进行验证确认,常见使用小端模式。


3.4.1大小端
大小端,是一种字节序,针对多字节数据。而单字节的数据例如char,不需要特意考虑大小端的问题。
首先明确区分两个高低,内存/存储地址高低,数据的高低字节

大端(Big-endian), 将数据的高位存储在内存的低地址处。
小端(Little-endian),将数据的低位存储在内存的低地址处。
“大小端”这个名词并不容易记忆和理解,它英文描述反而看起来更直观形象。例如,将“大端”翻译成“高尾端"更容易被理解,内存高地址存放数据的尾部低字节。大小指的是内存/存储地址,端指的是数据结束端,也就是数据的结束端字节(也就是最低字节)。

模式大小
大端(Big-endian)内存高地址数据的低字节
小端(Little-endian)内存低地址数据的低字节

例如数据 int a=0x12345678,在大小端系统中的存储。

内存地址大端小端
高地址00000004尾字节7812
000000035634
000000023456
低地址0000000112尾字节78

换一种更直接的理解和记忆方式,由于计算机总是从低地址往高地址方向读取,大端模式,先读到高字节,小端模式先读到低字节
基于这个特性使得大小端模式表现出各自的优缺点,符号位在高字节,大端模式能快速判断数据的正负和大小。小端模式,数据字节顺序和内存地址顺序一致,计算机按顺序读取更加高效。同时进行强制类型转换时,可以直接截取,不需要再调整内容。


3.4.2 位序
大小端,是指字节间的排序。字节内部的排序用位序表示。
位序,也叫比特序,分为LSB和MSB两种。
首先明确区分两个高低,内存/存储地址单字节空间内的bit高低位号,数据单字节内的bit权重高低位

LSB(least significant bit):数据的最低权重位存放在内存字节的第0位。
MSB (most significant bit):数据的最高权重位存放在内存字节的第0位。

小端模式下,只能使用LSB位序模式。
大端模式下,可以使用MSB位序模式,也可以使用LSB,大部分情况使用MSB。
在这里插入图片描述
无论LSB还是MSB,CPU都从内存中的低位开始读取,在MSB中读取到的0位内容为数据的高位,在LSB中读取到的0位内容为数据低位。虽然图中数据的存储在内存中不一样,但实际表示的都是同样的数据。对于一般的存储读取操作,字节序及位序并不影响数据读取结果。

但如果涉及大端系统与小端系统进行通信,或对数据进行分割截取,例如强制类型转换,就需要考虑字节序及位序影响。

在C结构体和位域中约定,无论LSB还是MSB,先定义的数据或位域总是放在低位地址。
可以这么理解,计算机总是从低位地址往高位地址寻址,总是先准备好低位的地址用来存储下一个数据,所以无论对结构体还是位域,先定义的数据先被分配,并优先分配到存储空间的低位地址的低位号。

先看LSB和MSB位序对单字节的影响。
在单字节下,小端模式和大端模式并不造成影响,但其默认采用的位序模式对数据造成了影响。

struct bs{
    unsigned  char a:1;
    unsigned  char b:2;
    unsigned  char c:5;    
    } ;
    
 union {
    struct bs n;
    unsigned char n_char;
   }u;
  
    u.n.a=1;
    u.n.b=1;
    u.n.c=1;
    printf("n_char=0x%.2x",u.n_char);

在LSB模式下,n_char= 0b00001011,0x0b
在MSB模式下,n_char=0b10100001,0xa1
在这里插入图片描述

在多字节下,也是一样的,先考虑位序的影响,同时还要附加考虑到大小端的影响。

struct bs{
    unsigned  short a:1;
    unsigned  short b:2;
    unsigned  short c:8;  
    unsigned  short d:2; 
    unsigned  short e:3; 
    } ;
    
 union {
    struct bs n;
    unsigned short n_short;
   }u;
  
    u.n.a=1;
    u.n.b=1;
    u.n.c=1;
    u.n.d=1;
    u.n.e=1;    
    printf("n_char=0x%.4x",u.n_short);

在小端模式LSB下,byte0 = 0x0b ,byte1 = 0b00101000 =0x28 ;小端模式下,byte1为高权重字节,n_short=0x280b;
在大端模式MSB下,byte0 = 0xa1,byte1 = 0b00101001 =0x29 ;大端模式下,byet1为低权重字节,n_short=0xa129;
在这里插入图片描述

可以看到同样的位域数据内容,存储在小端模式和大端模式下,进行整体取值后的值,变成了两个不同的值。所以在采用大端和小端的设备间进行相互通信,需要对数据进行转换后发送,或接收后重新解析。


3.4.3网络序
TCP/IP中,规定了自己的格式,与具体的CPU,操作系统等无关。从而保证了不同主机间通信格式统一。TCP/IP采用大端字节序,小端序主机进行大端网络序TCP/IP通信时候,需要使用htonl()、ntohl()等进行位序转换。
注:网络资料介绍:htonl()只做了字节序的转换,并没有进行比特序的转换。该知识涉及到更深入的网络通信底层,目前还不能理解。

总结

**位域的特点:**减少数据存储,提高代码阅读性,不利于平台兼容。

**位域的推荐使用方法:**简单的去使用位域,
位域推荐使用无符号类型,并尽量使用同一种类型,推荐使用unsigned int。将同类型的位域数据放在一起,尽量将位域数据成员相邻放置在一起,或单独打包成一个结构体。

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

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

相关文章

VM安装linux虚拟机宿主机连接不上虚拟机问题处理及静态ip设置

VM安装linux虚拟机宿主机连接不上虚拟机问题处理 用 vm安装linux虚拟机宿主机连不上虚拟机&#xff0c;ipconfig宿主机发现VMnet1以及VMnet8的Ip都变成了169.254开头的地址&#xff0c;网上各种方式都试了都不行&#xff0c;要么 是 虚拟机连不上网&#xff0c;要么 是宿主机连…

金融测试岗面试有多难?我有秘招……

最近发现好多人都喜欢往金融测试岗跑&#xff0c;看来是真的很香了&#xff0c;但是你们知不知道面试金融测试岗还是很难的&#xff0c;如果想去面试真的要多做些了解再去&#xff0c;我在这里总结了一份面试文档分享给大家&#xff0c;若有需要&#xff0c;【留言777】即可。 …

windows 系统加固

其实Windows和Linux加固的方法都差不多 1.防火墙 1.防火墙的开启 2.入站规则进行设置 对一些端口更改后可以使用telnet 进行检测端口是否开放 2.安装杀毒软件 3.扫描漏洞&#xff0c;打补丁 一般漏洞扫描可以借用第三方平台对系统漏洞进行扫描。 开启补丁的自动更新 4.用…

【css系列】八股2023/6/18

1.说说设备像素、css像素、设备独立像素、dpr、ppi 之间的区别&#xff1f; css 像素&#xff1a;长度单位&#xff0c;在css规范中&#xff0c;长度单位分为两类&#xff1a;绝对单位 和 相对单位。 设备像素&#xff1a;物理像素&#xff0c;指设备能控制显示的最小物理单位…

计算机视觉的应用8-基于ResNet50对童年数码宝贝的识别与分类

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下计算机视觉的应用8-基于ResNet50对童年数码宝贝的识别与分类&#xff0c;想必做完90后的大家都看过数码宝贝吧&#xff0c;里面有好多类型的数码宝贝&#xff0c;今天就给大家简单实现一下&#xff0c;他们的分类任…

计网大题(6/18)

1.奈奎斯特定理和香农公式 1.奈奎斯特 B1/T ,T是波特 &#xff0c;B成为波特率 奎氏定理&#xff1a;R2Wlog2&#xff08;N&#xff09; &#xff08;W是理想信道带宽&#xff0c;单位是hz&#xff09; 香农公式 R是最大信道容量 信道带宽是W 信噪比是S/N ,(S是平均信号功率…

kotlin学习(二)泛型、函数、lambda、扩展、运算符重载

文章目录 泛型&#xff1a;in、out、where型变&#xff08;variance&#xff09;不变&#xff08;Invariant&#xff09;协变&#xff08;Covariant&#xff09;Java上界通配符<? extends T>Kotlin的关键词 outUnsafeVariance 逆变&#xff08;Contravariant&#xff09…

Portraiture4.1智能磨皮滤镜插件下载安装使用教程

ps磨皮插件portraiture是一款用于修饰人像照片的插件&#xff0c;可以在Photoshop中使用。它可以通过智能算法来自动识别照片中的肤色区域&#xff0c;然后对其进行磨皮处理&#xff0c;使得肌肤更加光滑细腻。不需要像曲线磨皮、中性灰磨皮那样需要复杂的操作&#xff0c;轻轻…

JavaScript之函数 (七):认识JavaScript函数、函数的声明和调用、函数的递归调用、局部和全局变量、函数表达式的写法、立即执行函数使用

1. 认识JavaScript函数 1.1 程序中的foo、bar、baz 在国外的一个问答网站stackover flow中&#xff0c;常常会使用这几个次进行变量&#xff0c;函数&#xff0c;对象等等声明&#xff0c;地位如同张三&#xff0c;李四&#xff0c;王五。foo、bar这些名词最早从什么时候、地…

【MySQL入门】-- 认识MySQL存储引擎

目录 1.MySQL存储引擎有什么用&#xff1f; 2.MySQL的存储引擎有哪些&#xff1f;分别有什么特点&#xff1f; 3.存储引擎的优缺点 4.关于存储引擎的操作 5. 存储引擎的选择&#xff1f; 6.InnoDB和MyISAM区别&#xff1f; 7.官方文档 1.MySQL存储引擎有什么用&#xff…

2022 年第十二届 MathorCup 高校数学建模挑战赛D题思路

目录 一、前言 二、问题背景 三、问题 四、解题思路 &#xff08;1&#xff09;针对问题1&#xff1a; &#xff08;2&#xff09;针对问题2&#xff1a; &#xff08;3&#xff09;针对问题3&#xff1a; 五、附上几个典型代码 &#xff08;1&#xff09;K-means算法…

文献阅读:Foundation Transformers

文献阅读&#xff1a;Foundation Transformers 1. 文章简介2. 模型结构 1. Sub-LN2. Initialization 3. 实验效果 1. NLP任务 1. 语言模型上效果2. MLM模型上效果3. 翻译模型上效果 2. Vision任务上效果3. Speech任务上效果4. 图文任务上效果 4. 结论 & 思考 文献链接&…

卡尔曼滤波器使用原理以及代码编写

注&#xff1a;要视频学习可以去B站搜索“DR_CAN”讲解的卡尔曼滤波器&#xff0c;深有体会&#xff01; 一、为啥需要卡尔曼滤波器 卡尔曼滤波器在生活中应用广泛&#xff0c;因为在我们生活中存在着不确定性&#xff0c;当我去描述一个系统&#xff0c;这个不确定性就包涵一…

源码编译LAMP与论坛安装

目录 Apache网站服务&#xff08;著名的开源Web服务软件&#xff09; Apache的主要特点 软件版本 如何创建论坛 安装相关服务Apache 安装MySQL数据库 安装PHP框架 然后进行论坛安装 第一步 先进入到MySQL内 第二步 授权bbs数据库 第三步 刷新数据库 第四步 解压指定…

【Windows】虚拟串口工具VSPD7.2安装

【Windows】虚拟串口工具VSPD7.2安装 1、背景2、VSPD7.2安装3、创建虚拟串口 1、背景 ​Virtual Serial Ports Driver​是由著名的软件公司Eltima制作的一款非常好用的​虚拟串口工具​&#xff0c;简称&#xff1a;VSPD。 VSPD其功能如同 Windows机器上COM 串行端口的仿真器…

Go-unsafe详解

Go语言unsafe包 Go语言的unsafe包提供了一些底层操作的函数&#xff0c;这些函数可以绕过Go语言的类型系统&#xff0c;直接操作内存。虽然这些函数很强大&#xff0c;但是使用不当可能会导致程序崩溃或者产生不可预料的行为。因此&#xff0c;使用unsafe包时必须小心谨慎。 …

小白必看!渗透测试的8个步骤

渗透测试与入侵的区别 渗透测试&#xff1a;以安全为基本原则&#xff0c;通过攻击者以及防御者的角度去分析目标所存在的安全隐患以及脆弱性&#xff0c;以保护系统安全为最终目标。 入侵&#xff1a;通过各种方法&#xff0c;甚至破坏性的操作&#xff0c;来获取系统权限以…

C++ 教程(15)——数组(包含实例)

C 支持数组数据结构&#xff0c;它可以存储一个固定大小的相同类型元素的顺序集合。数组是用来存储一系列数据&#xff0c;但它往往被认为是一系列相同类型的变量。 数组的声明并不是声明一个个单独的变量&#xff0c;比如 number0、number1、...、number99&#xff0c;而是声…

[架构之路-215]- 系统分析-领域建模基本概念

目录 1. 什么是领域或问题域 2. 什么面向对象的“类” 》 设计类 3. 什么是概念类 4. 什么是领域建模 5. 领域建模与DDD&#xff08;领域驱动架构设计&#xff09;的关系 6. 领域建模的UML方法 7. 领域建模的案例 其他参考&#xff1a; 1. 什么是领域或问题域 领域&a…

Spring AOP之MethodInterceptor原理

文章目录 引言Spring AOP组成先看一下Advice 示例提问 原理 引言 之前我们讨论过了HandlerInterceptor&#xff0c;现在我们来看一下MethodInterceptor。 MethodInterceptor是Spring AOP中的一个重要接口,用来拦截方法调用&#xff0c;它只有一个invoke方法。 Spring AOP组成…