哪里有网站开发平台/网络营销策略的内容

哪里有网站开发平台,网络营销策略的内容,铁岭做网站的公司,大丰哪家专业做网站什么是 spring 的循环依赖? 首先,认识一下什么是循环依赖,举个例子:A 对象被 Spring 管理,并且引入的 B 对象,同样的 B 对象也被 Spring 管理,并且也引入的 A 对象。这种相互被引用的情况&#…

什么是 spring 的循环依赖?


首先,认识一下什么是循环依赖,举个例子:A 对象被 Spring 管理,并且引入的 B 对象,同样的 B 对象也被 Spring 管理,并且也引入的 A 对象。这种相互被引用的情况,就是所谓的循环依赖

@Component
public class A {@Autowiredprivate B b;
}
@Component
public class B {@Autowiredprivate A a;
}

我们都知道,Spring 是将对象给管理起来,这些对象默认还都是单例的,需要的话从 Spring 中直接取出即可。

1. Spring 是如何存储这些 Bean 呢?

Spring 通过 Map 结构将对象给缓存起来,这里的 Map 其实是分为三个:

  1. 一级缓存(singletonObjects):此缓存中的对象是已经完全创建好的,可以直接使用的 Bean;

    Map<String, Object> singletonObjects = new ConcurrentHashMap<>();
    
  2. 二级缓存(earlySingletonObjects):此缓存中存储尚未完全初始化但已经创建了对象实例的 Bean(即提前暴露的 Bean 实例)

    Map<String, Object> earlySingletonObjects = new HashMap<>();
    
  3. 三级缓存(singletonFactories):比较特殊,存放的是 ObjectFactory,这是一个工厂,等到从缓存中取时,会执行其中的 getObject() 方法,来得到代理对象

    Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>()
    

    这样设计是为了在有 AOP 的情况下,可以返回代理对象,而且也能满足循环依赖。

2. 循环依赖的创建过程

  1. 当对象 a 被创建时,就会在缓存中进行查询,先从一级缓存中进行查询,如果没有,接着再从二级缓存中进行查询,如果依旧没用,最后从第三级缓存中查询,如果还是没有,就接着执行后续操作;

  2. 由于缓存中没有 a 对象,就要回到主流程,执行 a 对象的创建

    1. 利用反射创建对象
    2. 这时候就要用到三级缓存,将创建出的对象包装成 ObjectFctory 类型,放到三级缓存中
  3. 填充 a 对象的属性(Bean 的引入也在此执行)

    其中要引入 b 对象,同样也要执行与 a 对象创建相同的流程:

    1. 查询缓存

    2. b 对象的创建:利用反射创建 b 对象,并存入三级缓存中

    3. 填充 b 对象的属性

      此时又要引入 a 对象,由于已经将 a 存储到缓存中,因此这里要执行一些额外的操作(后面说)后,将得到的 a 对象填充到 b 对象中

    4. 初始化

    5. 缓存转移(具体步骤后面说

  4. a 对象初始化

  5. 缓存转移

总体流程大致如下:

3. 补充说明

3.1 在 b 对象创建中填充属性时,从缓存中读取 a 对象要经过什么操作?

参考源码,读取关键部分(红框位置):


首先从三级缓存中获取到 a 对象,由于这个缓存里存放的是 ObjectFactory 类型,并不是真正的对象,这里就要执行 getObject() 方法,从而创建出真正要使用的对象,将得到的真正的对象 a 存入二级缓存中,并将三级缓存中的 a 删除。

3.2 缓存转移的步骤是什么?

此时 b 已经完全创建完毕,所以要将缓存里面的对象进行转移,参考源码:


可以分析出具体操作为:

  1. 将 b 的完整对象放到一级缓存中
  2. 将三级缓存中的 b 移除掉
  3. 将二级缓存中的 b 移除掉(该场景下二级缓存中并没有 b 对象)

a 对象的缓存转移也是同理。

4. 扩展

4.1 第三级缓存的作用?

从上面的执行步骤,可以感觉到三级缓存和里面的 ObjectFactory 类型似乎有点多余,有一级、二级缓存也能搞定循环依赖,三级缓存的意义是什么?

其实主要作用就是为了 AOP。

举例:假如对 b 对象使用了 AOP 切面功能,那么 a 对象引入的 b 对象就必须是 b 对象的代理对象,当 Spring 在没有循环依赖的情况下,是先将普通的完整对象创建好之后,再生成对应的代理对象,然而 Spring 并没有办法提前知道这个对象有没有循环依赖,也不能直接将每个对象都创建出代理对象,所以就需要吧对象包装成 ObjectFactory 类型,提前曝光,等从三级缓存中获取到 ObjectFactory 后,就可以通过 getObject() 方法生成代理对象。

4.2 避免循环依赖的最佳实践

尽管 Spring 提供了循环依赖的解决方案,但在实际开发中应尽量避免循环依赖,因为它可能导致代码耦合度过高、可维护性差等问题。以下是一些避免循环依赖的建议:

  1. 重构代码:将公共逻辑提取到第三个类中,打破循环依赖。
  2. 使用接口或事件驱动:通过接口或事件机制解耦组件间的直接依赖。
  3. 谨慎使用构造器注入:对于可能存在循环依赖的场景,优先使用 Setter 注入

4.3 构造器注入与 Setter 注入的区别

  1. Setter 注入:支持循环依赖。因为 Spring 可以通过三级缓存机制提前暴露部分初始化的 Bean 实例
  2. 构造器注入:不支持循环依赖。原因在于构造器注入要求在创建 Bean 时必须提供所有依赖项,而循环依赖会导致死锁(A 等待 B,B 等待 A)。

因此,如果使用构造器注入,循环依赖会导致 BeanCurrentlyInCreationException 异常。

BeanCurrentlyInCreationException 异常:表示在尝试实例化一个 Bean 时,Spring 容器检测到正在创建的 Bean 已经在创建过程中,导致循环依赖。这种异常通常是由于循环依赖问题引起的。

5. 总结

Spring 通过三级缓存机制解决了单例 Bean 之间的循环依赖问题,但对于原型 Bean 或构造器注入的场景,Spring 无法解决循环依赖。开发时应尽量避免循环依赖,保持代码的清晰性和可维护性

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

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

相关文章

STM32旋转编码器驱动详解:方向判断、卡死处理与代码分析 | 零基础入门STM32第四十八步

主题内容教学目的/扩展视频旋转编码器电路原理&#xff0c;跳线设置&#xff0c;结构分析。驱动程序与调用。熟悉电路和驱动程序。 师从洋桃电子&#xff0c;杜洋老师 &#x1f4d1;文章目录 一、旋转编码器原理与驱动结构1.1 旋转编码器工作原理1.2 驱动程序结构 二、方向判断…

elementplus的cascader级联选择器在懒加载且多选时的一些问题分析

1. 背景 在之前做的一个项目中使用到了element的级联选择器&#xff0c;并且是需要懒加载、多选、父子不关联等等&#xff0c;在选的时候当然没问题&#xff0c;但是回显的时候就会回显不出来&#xff0c;相信大部分伙伴都遇到过这个问题。我在以前出过一篇文章写过关于级联选…

【Linux实践系列】:用c语言实现一个shell外壳程序

&#x1f525;本文专栏&#xff1a;Linux Linux实践项目 &#x1f338;博主主页&#xff1a;努力努力再努力wz 那么今天我们就要进入Linux的实践环节&#xff0c;那么我们之前学习了进程控制相关的几个知识点&#xff0c;比如进程的终止以及进程的等待和进程的替换&#xff0c;…

⭐算法OJ⭐N-皇后问题 II【回溯剪枝】(C++实现)N-Queens II

⭐算法OJ⭐N-皇后问题【回溯剪枝】&#xff08;C实现&#xff09;N-Queens 问题描述 The n-queens puzzle is the problem of placing n n n queens on an n n n \times n nn chessboard such that no two queens attack each other. Given an integer n, return the num…

03.06 QT

一、使用QSlider设计一个进度条&#xff0c;并让其通过线程自己动起来 程序代码&#xff1a; <1> Widget.h: #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QThread> #include "mythread.h"QT_BEGIN_NAMESPACE namespace Ui {…

地下井室可燃气体监测装置:守护地下安全,防患于未“燃”!

在城市的地下&#xff0c;隐藏着无数的燃气管道和井室&#xff0c;它们是城市基础设施建设的重要部分&#xff0c;燃气的使用&#xff0c;给大家的生活提供了极大的便利。在便利生活的背后&#xff0c;也存在潜在的城市安全隐患。 近年来&#xff0c;地下井室可燃气体泄漏事故…

【使用hexo模板创建个人博客网站】

使用hexo模板创建个人博客网站 环境准备node安装hexo安装ssh配置 使用hexo命令搭建个人博客网站hexo命令 部署到github创建仓库修改_config.yml文件 编写博客主题扩展 环境准备 node安装 进入node官网安装node.js 使用node -v检查是否安装成功 安装成功后应该出现如上界面 …

C# OPC DA获取DCS数据(提前配置DCOM)

OPC DA配置操作手册 配置完成后&#xff0c;访问远程ip&#xff0c;就能获取到服务 C#使用Interop.OPCAutomation采集OPC DA数据&#xff0c;支持订阅&#xff08;数据变化&#xff09;、单个读取、单个写入、断线重连

发行思考:全球热销榜的频繁变动

几点杂感&#xff1a; 1、单机游戏销量与在线人数的衰退是剧烈的&#xff0c;有明显的周期性&#xff0c;而在线游戏则稳定很多。 如去年的某明星游戏&#xff0c;最高200多万在线&#xff0c;如今在线人数是48名&#xff0c;3万多。 而近期热门的是MH&#xff0c;在线人数8…

Unity自定义区域UI滑动事件

自定义区域UI滑动事件 介绍制作1.创建一个Image2.创建脚本 总结 介绍 一提到滑动事件联想到有太多的插件了比如EastTouchBundle&#xff0c;今天想单纯通过UI去做一个滑动事件而不是基于Box2d或者Box去做滑动事件。 制作 1.创建一个Image 2.创建脚本 using UnityEngine; us…

taosd 写入与查询场景下压缩解压及加密解密的 CPU 占用分析

在当今大数据时代&#xff0c;时序数据库的应用越来越广泛&#xff0c;尤其是在物联网、工业监控、金融分析等领域。TDengine 作为一款高性能的时序数据库&#xff0c;凭借独特的存储架构和高效的压缩算法&#xff0c;在存储和查询效率上表现出色。然而&#xff0c;随着数据规模…

《UE5_C++多人TPS完整教程》学习笔记34 ——《P35 网络角色(Network Role)》

本文为B站系列教学视频 《UE5_C多人TPS完整教程》 —— 《P35 网络角色&#xff08;Network Role&#xff09;》 的学习笔记&#xff0c;该系列教学视频为计算机工程师、程序员、游戏开发者、作家&#xff08;Engineer, Programmer, Game Developer, Author&#xff09; Stephe…

微信小程序引入vant-weapp组件教程

本章教程,介绍如何在微信小程序中引入vant-weapp。 vant-weapp文档:https://vant-ui.github.io/vant-weapp/#/button 一、新建一个小程序 二、npm初始化 npm init三、安装 Vant Weapp‘ npm i @vant/weapp -

C++ 作业 DAY5

作业 代码 Widtget.h class Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent nullptr);~Widget();private:Ui::Widget *ui;/************************ 起始终止坐标 ************************/QPoint end;QPoint start;QVector<QPoint> per_start_lis…

【js逆向】iwencai国内某金融网站实战

地址&#xff1a;aHR0cHM6Ly93d3cuaXdlbmNhaS5jb20vdW5pZmllZHdhcC9ob21lL2luZGV4 在搜索框中随便输入关键词 查看请求标头&#xff0c;请求头中有一个特殊的 Hexin-V,它是加密过的&#xff1b;响应数据包中全是明文。搞清楚Hexin-V的值是怎么生成的&#xff0c;这个值和cooki…

使用Node.js从零搭建DeepSeek本地部署(Express框架、Ollama)

目录 1.安装Node.js和npm2.初始化项目3.安装Ollama4.下载DeepSeek模型5.创建Node.js服务器6.运行服务器7.Web UI对话-Chrome插件-Page Assist 1.安装Node.js和npm 首先确保我们机器上已经安装了Node.js和npm。如果未安装&#xff0c;可以通过以下链接下载并安装适合我们操作系…

BUUCTF——[GYCTF2020]FlaskApp1 SSTI模板注入/PIN学习

目录 一、网页功能探索 二、SSTI注入 三、方法一 四、方法二 使用PIN码 &#xff08;1&#xff09;服务器运行flask登录所需的用户名 &#xff08;2&#xff09;modename &#xff08;3&#xff09;flask库下app.py的绝对路径 &#xff08;4&#xff09;当前网络的mac地…

FPGA学习篇——Verilog学习3(关键字+注释方法+程序基本框架)

1 Verilog常用关键字 大概知道以下哪些是关键字就好&#xff0c;如何使用还是得在编写代码中来学习。 2 Verilog注释方法 Verilog有两种注释方式&#xff1a; 2.1 “ // ” 单行。 2.2 “ /* ... */ ” 可扩展多行。 3 Verilog程序基本框架 Verilog 的基本设计单元是“…

FPGA之USB通信实战:基于FX2芯片的Slave FIFO回环测试详解

FPGA之Usb数据传输 Usb 通信 你也许会有疑问&#xff0c;明明有这么多通信方式和数据传输&#xff08;SPI、I2C、UART、以太网&#xff09;为什么偏偏使用USB呢? 原因有很多&#xff0c;如下&#xff1a; 1. 高速数据传输能力 高带宽&#xff1a;USB接口提供了较高的数据传…

深入理解与配置 Nginx TCP 日志输出

一、背景介绍 在现代网络架构中&#xff0c;Nginx 作为一款高性能的 Web 服务器和反向代理服务器&#xff0c;广泛应用于各种场景。除了对 HTTP/HTTPS 协议的出色支持&#xff0c;Nginx 从 1.9.0 版本开始引入了对 TCP 和 UDP 协议的代理功能&#xff0c;这使得它在处理数据库…