当前位置: 首页 > news >正文

auth模块

一. auth模块前戏

# 引入:其实我们在创建好一个django项目之后直接执行数据库迁移命令会自动生成很多表 例如:django_sessionauth_user我们知道django在启动之后就可以直接访问admin路由,需要输入用户名和密码,数据参考的就是auth_user表,并且还必须是管理员用户才能进入,现在我们就可以通过在命令行中执行创建超级用户(管理员)的命令, 来创建你的admin用户python3 manage.py createsuperuser# auth模块作用:主要就是依赖于auth_user表完成用户相关的所有功能.

二. auth模块方法及使用

主要分为登录认证, 保存用户状态, 判断当前用户是否登陆, 获取当前登陆用户, 登录认证装饰器, 密码核对, 修改密码, 注销当前登录用户, 注册

1. 登录认证

# 登录认证: 比对用户名和密码是否正确
'''
效验成功返回用户对象. 效验失败返回None.
注意: request可以不指定默认就是None,  而括号内必须同时传入用户名和密码. 不能只指定一个.
'''
from django.contrib import auth
user_obj = auth.authenticated(request, username=username, password=password)
print(user_obj)           # jason  提示: 返回用户对象, 只是内部书写了__str__烦伐. 如果数据不符合则返回None
print(user_obj.username)  # jason
print(user_obj.password)  # pbkdf2_sha256$36000$zeNDf8CkZj7y$b+e/CjzZoAnbBIpvUWgz25ybBDqDzRTmYAHPytxqRYQ=

2. 保存用户状态

# 保存用户状态:
'''
1. 内部自动查找auth_user标签
2. 内部自动给密码加密再比对
提示: 只要执行了该方法 你就可以在任何地方通过request.user获取到当前登陆的用户对象
'''
auth.login(request, user_obj)   # 内部调用的就是 request.session['key']=user_obj

3. 判断当前用户是否登陆

# 判断当前用户是否登陆:
request.user.is_authenticated()

4. 获取当前登陆用户

# 获取当前登陆用户:
'''
1. 获取浏览器提交过来的sessionid对应的随机字符串
2. 后端拿到随机字符串到django_session表中获取数据2-1. 如果浏览器提交的随机字符串没有匹配上. 返回 AnonymousUser 匿名用户2-2. 如果浏览器提交的随机字符串有匹配上了. 返回对应的用户对象
'''
request.user  # 匹配上返回对应用户对象. 没有匹配上返回 AnonymousUser 对象

5. 登录认证装饰器

# 登录认证装饰器:
from django.contrib.auth.decorators import login_required
# 局部设置@login_required(login_url='/login/')   # login_url 控制跳到指定的页面.  否则会以accounts打头, 跟随你的登录页面路径/login/?next=/my_home/
# 全局设置到settings.py中书写: LOGIN_URL = '/login/'@login_required    # 之后的装饰器使用就不需要传login_url参数了
# 优先级: 局部 > 全局
# 局部优缺点:缺点: 如果争对需要装饰的对象都是在没有登录以后跳转到同一个页面代码就会显得冗余 .优点: 不同的视图函数在用户没有登陆的情况下可以跳转到不同的页面
# 全局优缺点:缺点: 跳转的页面却很单一优点: 全局的好处在于无需重复写代码

6. 密码核对

# 密码核对: 比对原密码
'''
会将old_password加密与原密码比对. 返回布尔值.
'''
is_correct = request.user.check_password(old_password)

7. 修改密码

# 修改密码:
'''
第一步仅仅是在修改对象的属性
第二步才是真正的操作数据进行保存
'''
request.user.set_password(new_password)
request.user.save()

8. 注销当前登录用户

# 注销当前登录用户:
auth.logout(request)  # 内部使用的就是 request.session.flush()

9. 注册

# 注册:
from django.contrib.auth.models import User
# 操作auth_user表写入数据
# 方式一: 密码无加密. 不推荐使用
User.object.create(username=username, password=password)# 方式二: 创建普通用户. 密码会进行加密
User.object.create_user(username=username, password=password)# 方式三: 超级用户创建(了解). 密码会进行加密. 代码创建的email必填. 命令行创建的可以不填
User.object.create_superuser(username=username, password=password, email='111@qq.com')

10. 代码示例

from django.contrib import authdef my_login(request):if request.method == 'POST':username = request.POST.get('username')password = request.POST.get('password')# 1. 登录认证: 比对用户名和密码是否正确'''user_obj = auth.authenticate(request, username=username, password=password)效验成功返回用户对象. 效验失败返回None.注意: request可以不指定默认就是None,  而括号内必须同时传入用户名和密码. 不能只指定一个.'''user_obj = auth.authenticate(request, username=username, password=password)print(user_obj, type(user_obj))  # None/egon  <class 'django.contrib.auth.models.User'>if user_obj:print('user_obj.username:', user_obj.username)  # egonprint('user_obj.password:',user_obj.password)  # pbkdf2_sha256$36000$PAy4tWE1NiBa$0vgeQMKwDK0U+F3KqiiiT+eEWmA9kD0Iq+mUON1jPLo=# 2. 保存用户状态:'''1. 内部自动查找auth_user标签2. 内部自动给密码加密再比对提示: 只要执行了该方法 你就可以在任何地方通过request.user获取到当前登陆的用户对象'''auth.login(request, user_obj)  # 内部调用的就是 request.session['key']=user_objtarget_url = request.GET.get('next')print('target_url:', target_url)  # target_url: None / target_url: /my_index/if target_url:obj = redirect(target_url)else:obj = redirect('/my_home/')return objreturn render(request, 'my_login.html')from django.contrib.auth.decorators import login_required# 4. 登录认证装饰器 优先级: 局部 > 全局
@login_required  # 全局
def my_home(request):# 3. 获取当前登陆用户:'''request.user  # 匹配上返回对应用户对象. 没有匹配上返回 AnonymousUser 对象1. 获取浏览器提交过来的sessionid对应的随机字符串2. 后端拿到随机字符串到django_session表中获取数据2-1. 如果浏览器提交的随机字符串没有匹配上. 返回 AnonymousUser 匿名用户2-2. 如果浏览器提交的随机字符串有匹配上了. 返回对应的用户对象'''print('request.user:', request.user)print('request.user.is_authenticated():', request.user.is_authenticated())return HttpResponse('这是 my_home 页面只有登录了的用户才能进来哦~')@login_required(login_url='/my_login/')  # 局部
def my_index(request):return HttpResponse('这是 my_index 页面只有登录了的用户才能进来哦~')from django.contrib.auth.models import User@login_required
def my_set_password(request):retain_dict = {  # 保留form表单提交后之前的数据. 这里先占位, 再赋值.'old_password': '','new_password': '','confirm_password': '',}error_dict = {  # 展示form表单输入错误的内容. 这里先占位, 再赋值.'old_password': '','new_password': '','confirm_password': '',}if request.method == 'POST':old_password = request.POST.get('old_password')new_password = request.POST.get('new_password')confirm_password = request.POST.get('confirm_password')retain_dict['old_password'] = old_passwordretain_dict['new_password'] = new_passwordretain_dict['confirm_password'] = confirm_passwordif confirm_password == new_password:# 5. 密码核对: 比对原密码  会将old_password加密与原密码比对. 返回布尔值.is_correct = request.user.check_password(old_password)print('is_correct:', is_correct)  # is_correct: Trueif is_correct:# 6. 修改密码:request.user.set_password(new_password)  # 仅仅是在修改对象的属性request.user.save()  # 这一步才是真正的操作数据库retain_dict.clear()return redirect('/my_login/')else:error_dict['old_password'] = '原密码不正确, 请核对后在输!'else:error_dict['new_password'] = '两次密码输入不一致!'error_dict['confirm_password'] = '两次密码输入不一致!'return render(request, 'my_set_password.html', locals())@login_required
def logout(request):auth.logout(request)  # 内部使用的就是 request.session.flush()return redirect("/my_login/")from django.contrib.auth.models import User
from app01 import modelsdef my_register(request):retain_dict = {'username': '','password': '','confirm_password': '','phone': '','addr': '',}error_dict = {'username': '','password': '','confirm_password': '','phone': '','addr': '',}if request.method == 'POST':username = request.POST.get('username')password = request.POST.get('password')confirm_password = request.POST.get('confirm_password')phone = request.POST.get('phone')addr = request.POST.get('addr')retain_dict['username'] = usernameretain_dict['password'] = passwordretain_dict['confirm_password'] = confirm_passwordretain_dict['phone'] = phoneretain_dict['addr'] = addrprint(retain_dict)if password == confirm_password:user_queryset = models.UserInfo.objects.filter(username=username)print('user_queryset:', user_queryset)if user_queryset:error_dict['username'] = '该用户已经存在!'else:# 7. 注册:# 方式一: 密码无加密. 不推荐使用# User.objects.create(username=username, password=password)# 方式二: 创建普通用户. 密码会进行加密User.objects.create_user(username=username, password=password)# 方式三: 超级用户创建(了解). 密码会进行加密. 代码创建的email必填. 命令行创建的可以不填# User.objects.create_superuser(username=username, password=password, email='111@qq.com')retain_dict.clear()return redirect('/my_login/')else:error_dict['password'] = '两次密码输入不一致!'error_dict['confirm_password'] = '两次密码输入不一致!'return render(request, 'my_register.html', locals())

三. 扩展auth_user表

from django.db import models
from django.contrib.auth.models import User
from django.contrib.auth.models import AbstractUser# 第一种: 建立一对一外键关系  (不推荐)
class UserDetail(models.Model):phone = models.BigIntegerField()user = models.OneToOneField(to='User')# 第二种:面向对象的继承
class UserInfo(AbstractUser):"""提示:如果继承了AbstractUser那么在执行数据库迁移命令的时候auth_user表就不会再创建出来了而UserInfo表中会出现auth_user所有的字段外加自己扩展的字段这么做的好处在于你能够直接点击你自己的表更加快速的完成操作及扩展继承的注意事项:1. 继承之前保证没有执行过数据库迁移命令保证auth_user没有被创建,如果当前库已经创建了那么你就重新换一个库2. 继承的类里面不要覆盖AbstractUser默认的的字段名表里面有的字段都不要动,只扩展额外字段即可3. 需要在settings.py配置文件中告诉django你要用UserInfo替代auth_user.AUTH_USER_MODEL = 'app01.UserInfo''应用名.表名'这句话的含义就类似于我们书写表类的完后, 执行完数据库迁移命令会生成的app01_userinfo这张表"""phone = models.BigIntegerField(verbose_name='用户手机号码')addr = models.CharField(max_length=255, verbose_name='家庭住址')# 使用: auth模块的功能还是照常使用,参考的表页只是由原来的auth_user变成了UserInfo# 原来的:from django.contrib.auth.models import UserUser.objects.create_user(username=username, password=password)# 现在的:from app01.models import UserInfoUserInfo.objects.create_use

补充: 如果auth_user表已经创建了, 还想使用. 但是你在迁移数据库执行migrate命令的时候, 会抛出异常, 那么操作方法参考如下连接即可:

ValueError: The field admin.LogEntry.user was declared with a lazy reference to 'system.sysuser', bu-CSDN博客

关于django makemigrations/migrate在生成数据表上遇到的一些问题-CSDN博客

四. 总结

# auth模块前戏# 本质: auth模块本质就是在执行完数据库迁移命令以后, 操作django自动生成的auth_user表.   django的admin后台管理需要用到该表# 命令行创建超级用户: python3.6 manage.py createsuperuser# auth模块方法及使用
# auth模块主要提供了登录认证, 保存用户状态, 判断当前用户是否登陆, 获取当前登陆用户, 登录认证装饰器, 密码核对, 修改密码, 注销当前登录用户, 注册等功能# 登录认证from django.contrib import authuser_obj = auth.authenticate(request, username=username, password=password)  # 认证成功返回用户对象, 否则返回None# 存储用户状态提示: 该方法执行完毕之后,在任意位置都可以通过request.user获取到当前登陆的用户对象auth.login(username=username, password=password)  # 内部就是操作request.session[key]=user_obj# 获取当前用户对象request.user# 判断当前用户是否登录request.user.is_authenticated()# 登录认证装饰器from django.contrib.auth.decorators import login_required# 局部@login_required(login_url='/login/')@login_required(login_url='/this_login/')# 全局先到settings.py配置文件中配置: LOGIN_URL = '/login/'@login_required# 优先级: 局部 > 全局# 效验密码is_correct = request.user.check_password(old_password)  # 效验结果是布尔值# 修改密码request.user.set_password(new_password)request.user.save()# 注册from django.contrib.auth.models import UserUser.objects.create(username=username, password=password)           # 密码无加密 , 不推荐使用User.objects.create_user(username=username, password=password)      # 创建普通用户User.objects.create_superuser(username=username, password=password, email='111@qq.com') # 创建管理员用户, 与命令行创建方式不同的是, 必须指定邮箱# 注销auth.logout(request)# 扩展auth_user表注意事项:1. 在没执行过数据库迁移命令之前, 执行了就换库.2. 必须要继承AbstractUser类, 且自定义字段不能与其类里面冲突3. 还需要到配置文件中进行声明: AUTH_USER_MODEL = '应用名.表名'from django.db import modelsfrom django.contrib.auth.models AbstractUserclass UserInfo(AbstractUser):phone = models.CharField(max_length=255)create_time = models.DateField(auto_now_add=True)使用方式换汤不换药:from app01.models import UserInfoUser.objects.create_user(username=username, password=password, phone=phone)        

 

相关文章:

auth模块

一. auth模块前戏 # 引入:其实我们在创建好一个django项目之后直接执行数据库迁移命令会自动生成很多表 例如:django_sessionauth_user我们知道django在启动之后就可以直接访问admin路由&#xff0c;需要输入用户名和密码&#xff0c;数据参考的就是auth_user表,并且还必须是管…...

H5ke12--3--iframe--编辑邮箱的制作

下面我们来window.iframes[] frames是一个全局变量&#xff0c;它是一个对象数组&#xff0c;其中包含当前窗口中的所有框架&#xff08;如果存在&#xff09;。 在这段代码中&#xff0c;let frameframes[0];是将第一个框架赋值给变量frame。通过frame.document.designMode&q…...

Python面经【3】

零、可迭代对象 可迭代对象是迭代器和生成器的基础&#xff0c;简单来说&#xff0c;可以使用for循环遍历的对象就是可迭代对象&#xff0c;比如常见的list、set和dict。在python中&#xff0c;可迭代对象是指实现了__iter__()方法的对象&#xff0c;当我们使用for循环遍历一个…...

Python集合类型

目录 目标 版本 官方文档 集合分类 实战 创建 循环 常用方法 目标 掌握set和frozenset两种集合的使用方法&#xff0c;包括&#xff1a;创建、交集、并集、差集等操作。 版本 Python 3.12.0 官方文档 Set Types — set, frozensethttps://docs.python.org/3/library/s…...

npm install报错常用解题思路

最近刚接手一个“新”项目&#xff0c;让我很无语。明明是去年起的项目&#xff0c;但是它所用的部分技术栈非常旧&#xff0c;我启动项目&#xff0c;控制台一堆warning报错&#xff0c;然后项目结构也很让我不适应&#xff0c;很多地方都可以用文件夹包一下来方便定位。哎&am…...

conda: error: argument COMMAND: invalid choice

简介 使用conda activate 时&#xff0c;可能会报&#xff1a;conda: error: argument COMMAND: invalid choice: ‘activate’ (choose from ‘clean’, ‘compare’, ‘config’, ‘create’, ‘info’, ‘init’, ‘install’, ‘list’, ‘notices’, ‘package’, ‘remo…...

数仓成本下降近一半,StarRocks 存算分离助力云览科技业务出海

成都云览科技有限公司倾力打造了凤凰浏览器&#xff0c;专注于为海外用户提供服务&#xff0c;公司致力于构建一个全球性的数字内容连接入口&#xff0c;为用户带来更为优质、高效、个性化的浏览体验。 作为数据驱动的高科技公司&#xff0c;从数据中挖掘价值一直是公司核心任务…...

Apache基线检查

一、确保对OS根目录禁用覆盖 当 AllowOverride 指令设置为 None 时,Apache 将禁止在该目录下使用 .htaccess 文件来覆盖任何配置项。这意味着,除非您在主配置文件中显式地指定,否则该目录下的任何 .htaccess 文件都将被忽略。 禁用 .htaccess 文件可以提高服务器的安全性,因…...

flink的集成测试

背景 日常测试中我们使用flink的TestHarness只能测试单个算子&#xff0c;很多情况下我们需要集成测试来测试真正的问题&#xff0c;所以在flink中进行集成测试还是非常有必要的&#xff0c;本文就来记录下如何在flink中进行集成测试 flink中进行集成测试 flink中进行集成测…...

gitee推荐-1Panel

以下内容来源于gitee。 gitee地址&#xff1a;1Panel: &#x1f525; &#x1f525; &#x1f525; 现代化、开源的 Linux 服务器运维管理面板。 大概和宝塔类似,但支持docker。在线体验&#xff1a;https://demo.1panel.cn/ 稍微试了下&#xff0c;没找到apache&#xff0c;…...

GEE 22:基于GEE实现物种分布模型(更新中。。。。。。)

物种分布模型 1. 数据点准备1.1 数据加载1.2 去除指定距离内的重复点1.3 定义研究区范围1.4 选择预测因子 1. 数据点准备 1.1 数据加载 首先需要将CSV文件导入到GEE平台中&#xff0c;同样也可以导入shp格式文件。 // 1.Loading and cleaning your species data *************…...

阿里云windwos 安装oracle数据库,外部用工具连接不上,只能在服务器本机通过127.0.0.1 连接

1. 首先检查阿里云服务器安全组端口是否开放 oracle 数据库端口 2. 其次找到oracle 安装的目录&#xff0c;打开这俩个文件&#xff0c;将localhost 修改为 服务器本机名称 3.重启oracle 监听服务&#xff0c;就可以连接了...

UniApp 中的 image 属性讲解

在 UniApp 中&#xff0c;image 是用于显示图片的组件&#xff0c;它具有多种属性&#xff0c;可以控制图片的展示方式和行为。下面我将为您讲解一些常用的 image 属性。 基本属性 src&#xff1a;指定要显示的图片资源路径&#xff0c;可以是本地路径或远程 URL。mode&#…...

卷积神经网络(CNN)车牌识别

文章目录 一、前言二、前期工作1. 设置GPU&#xff08;如果使用的是CPU可以忽略这步&#xff09;2. 导入数据3. 查看数据3.数据可视化4.标签数字化 二、构建一个tf.data.Dataset1.预处理函数2.加载数据3.配置数据 三、搭建网络模型四、设置动态学习率五、编译六、训练八、保存和…...

弹窗concrt140.dll丢失的解决方法,深度解析concrt140.dll丢失的原因

在计算机使用过程中&#xff0c;我们经常会遇到一些错误提示或者系统崩溃的情况。其中&#xff0c;concrt140.dll是一个常见的错误提示&#xff0c;这个错误通常会导致某些应用程序无法正常运行。为了解决这个问题&#xff0c;本文将介绍5种详细的解决方法&#xff0c;帮助您恢…...

CANdelaStudio 使用教程4 编辑State

文章目录 简述1、State Groups2、Dependencies3、 Defaults State1、 会话状态2、 新增会话状态3、 编辑 服务对 State 的依赖关系 State Diagram 简述 1、State Groups 2、Dependencies 在这里&#xff0c;可以编辑现有服务在不同会话状态或安全访问状态的支持情况和状态转换…...

FANUC机器人到达某个点位时,为什么不显示@符号?

FANUC机器人到达某个点位时,为什么不显示@符号? 该功能由变量$MNDSP_POSCF = 0(不显示)/1(显示)/2(光标移动该行显示) 控制,该变量设置为不同的值,则启用对应的功能。 如下图所示,为该变量设置不同的值时的对比, 其他常用的系统变量可参考以下内容: 在R寄存器指定速度…...

JVM运行参数介绍 -Xms -Xmx -Xmn -Xss

文章目录 CharGPT问答Java运行参数“-Xmx2048m -Xms1024m -Xmn512m -Xss256k”如何调优jvm的运行参数 JVM相关介绍Java 虚拟机底层原理知识总结 CharGPT问答 Java运行参数“-Xmx2048m -Xms1024m -Xmn512m -Xss256k” 2023/11/26 20:30:27 这些参数是用于配置 Java 虚拟机&am…...

Hive删除符合条件的记录

Hive在使用中不支持update和delete操作&#xff0c;那么如果想删除部分条件的记录需要怎么操作&#xff1f;本文记录下解决方法。 思路&#xff1a;使用selectwhere选出想要保留的数据&#xff0c;使用insert overwrite向原表覆盖插入数据. insert overwrite table dbname.tab…...

Linux加强篇006-存储结构与管理硬盘

目录 前言 1. 从“/”开始 2. 物理设备命名规则 3. 文件系统与数据资料 4. 挂载硬件设备 5. 添加硬盘设备 6. 添加交换分区 7. 磁盘容量配额 8. VDO虚拟数据优化 9. 软硬方式链接 前言 悟已往之不谏&#xff0c;知来者之可追。实迷途其未远&#xff0c;觉今是而昨非…...

【Linux】shell脚本忽略错误继续执行

在 shell 脚本中&#xff0c;可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行&#xff0c;可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令&#xff0c;并忽略错误 rm somefile…...

云计算——弹性云计算器(ECS)

弹性云服务器&#xff1a;ECS 概述 云计算重构了ICT系统&#xff0c;云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台&#xff0c;包含如下主要概念。 ECS&#xff08;Elastic Cloud Server&#xff09;&#xff1a;即弹性云服务器&#xff0c;是云计算…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】

微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来&#xff0c;Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...

Appium+python自动化(十六)- ADB命令

简介 Android 调试桥(adb)是多种用途的工具&#xff0c;该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具&#xff0c;其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利&#xff0c;如安装和调试…...

Java如何权衡是使用无序的数组还是有序的数组

在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...

MMaDA: Multimodal Large Diffusion Language Models

CODE &#xff1a; https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA&#xff0c;它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构&#xf…...

oracle与MySQL数据库之间数据同步的技术要点

Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异&#xff0c;它们的数据同步要求既要保持数据的准确性和一致性&#xff0c;又要处理好性能问题。以下是一些主要的技术要点&#xff1a; 数据结构差异 数据类型差异&#xff…...

【论文笔记】若干矿井粉尘检测算法概述

总的来说&#xff0c;传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度&#xff0c;通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...

数据链路层的主要功能是什么

数据链路层&#xff08;OSI模型第2层&#xff09;的核心功能是在相邻网络节点&#xff08;如交换机、主机&#xff09;间提供可靠的数据帧传输服务&#xff0c;主要职责包括&#xff1a; &#x1f511; 核心功能详解&#xff1a; 帧封装与解封装 封装&#xff1a; 将网络层下发…...

Spring是如何解决Bean的循环依赖:三级缓存机制

1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间‌互相持有对方引用‌,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...