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

Spring三级缓存解决循环依赖

Spring三级缓存解决循环依赖

一 Spring bean对象的生命周期

在这里插入图片描述

二 三级缓存解决循环依赖

  1. 实现原理解析
    spring利用singletonObjects, earlySingletonObjects, singletonFactories三级缓存去解决的,所说的缓存其实也就是三个Map
    在这里插入图片描述
    在这里插入图片描述
    先实例化的bean会通过ObjectFactory半成品提前暴露在三级缓存中
    在这里插入图片描述
    我们假设现在有这样的场景AService依赖BService,BService依赖AService

(1) AService首先实例化,实例化通过ObjectFactory半成品暴露在三级缓存中

(2)填充属性BService,发现BService还未进行过加载,就会先去加载BService

(3)再加载BService的过程中,实例化,也通过ObjectFactory半成品暴露在三级缓存

(4)填充属性AService的时候,这时候能够从三级缓存中拿到半成品的ObjectFactory
在这里插入图片描述
拿到ObjectFactory对象后,调用ObjectFactory.getObject()方法最终会调用getEarlyBeanReference()方法,getEarlyBeanReference这个方法主要逻辑大概描述下如果bean被AOP切面代理则返回的是beanProxy对象,如果未被代理则返回的是原bean实例。

这时我们会发现能够拿到bean实例(属性未填充),然后从三级缓存移除,放到二级缓存earlySingletonObjects中,而此时B注入的是一个半成品的实例A对象,不过随着B初始化完成后,A会继续进行后续的初始化操作,最终B会注入的是一个完整的A实例,因为在内存中它们是同一个对象。

如果这个bean被AOP进行了切面代理,singleFactory.getObject()方法每次执行都会是一个新的代理对象,假设这里只有一级和三级缓存的话,我每次从三级缓存中拿到singleFactory对象,执行getObject()方法又会产生新的代理对象,这是不行的,因为AService是单例的,所有这里我们要借助二级缓存来解决这个问题,将执行了singleFactory.getObject()产生的对象放到二级缓存中去,后面去二级缓存中拿,没必要再执行一遍singletonFactory.getObject()方法再产生一个新的代理对象,保证始终只有一个代理对象。

  1. 总结
    为了解决循环依赖问题,Spring采用三级缓存(Three-Level Cache)的机制。具体步骤如下:

(1) 创建对象并放入singletonObjects缓存:当创建一个Bean时,Spring会先尝试从singletonObjects缓存中获取该Bean实例,如果找到则直接返回。如果没有找到,则进入下一步。

(2)提前暴露对象:在创建Bean的过程中,当Spring发现存在循环依赖时,会先提前暴露正在创建的Bean,并将其放入earlySingletonObjects缓存中。这样可以避免后续循环依赖时的死锁情况。

(3)创建对象并完成依赖注入:Spring会继续创建当前Bean,并进行依赖注入。如果依赖中仍然存在循环依赖,Spring会使用ObjectFactory或Provider延迟注入依赖。这样可以确保所有的依赖都已经创建完成。

(4)添加到singletonObjects缓存:当Bean创建完成后,会将其放入singletonObjects缓存中,以供后续的依赖注入使用。

  1. 解决办法
    在Spring中,如果出现循环依赖问题,可以采取以下几种方式来解决:

(1)构造函数注入:使用构造函数注入代替字段注入或setter注入。通过将依赖关系作为构造函数的参数传递,而不是直接在类中定义成员变量,并确保依赖关系的顺序正确,可以避免循环依赖的问题。

(2)使用@Lazy注解:使用@Lazy注解延迟加载Bean。通过在循环依赖的其中一个Bean上添加@Lazy注解,使其延迟初始化,从而打破循环依赖的死锁情况。

(3)使用代理模式:当出现循环依赖时,可以通过使用代理模式来解决。Spring提供了两种类型的代理:JDK动态代理和CGLIB代理。可以根据具体情况选择合适的代理方式。

(4)使用Setter注入:将字段注入改为使用setter注入。通过在setter方法上使用@Autowired注解,显式地控制依赖关系的注入顺序,以避免循环依赖。

(5)重新设计代码结构:有时,循环依赖问题可能是由于类之间的紧密耦合导致的。在这种情况下,重新审视代码结构,将相关的功能进行合理划分,减少或消除循环依赖。

相关文章:

Spring三级缓存解决循环依赖

Spring三级缓存解决循环依赖 一 Spring bean对象的生命周期 二 三级缓存解决循环依赖 实现原理解析 spring利用singletonObjects, earlySingletonObjects, singletonFactories三级缓存去解决的,所说的缓存其实也就是三个Map 先实例化的bean会通过ObjectFactory半…...

Vscode自动移出不用的包

Vscode自动移出不用的包 在Vscode中删除不用的包、Vscode移出不用的包、Vscode移出不用的import包 设置 找到setting.json(在字体设置里面),添加如下配置 "editor.codeActionsOnSave": { "source.organizeImports": tru…...

leetcode做题笔记120. 三角形最小路径和

给定一个三角形 triangle ,找出自顶向下的最小路径和。 每一步只能移动到下一行中相邻的结点上。相邻的结点 在这里指的是 下标 与 上一层结点下标 相同或者等于 上一层结点下标 1 的两个结点。也就是说,如果正位于当前行的下标 i ,那么下一…...

weblogic/CVE-2018-2894文件上传漏洞复现

启动docker环境 查看帮助文档 环境启动后,访问http://your-ip:7001/console,即可看到后台登录页面。 执行docker-compose logs | grep password可查看管理员密码,管理员用户名为weblogic,密码为lFVAJ89F 登录后台页面,…...

windows10默认浏览器总是自动更改为Edge浏览器

在设置的默认应用设置中把默认浏览器改为chrome或其他之后他自动又会改回Edge。不得不说*软真的狗。 解决办法: 后来发现在Edge浏览器的设置中有这么一个选项,会很无耻的默认是Edge。把它关掉后重新设置就行了。...

系统架构设计师考试论文:论软件架构风格与应用

软件体系结构风格是描述某一特定应用领域中系统组织方式的惯用模式。体系结构风格定义一个系统家族,即一个体系结构定义一个词汇表和一纽约束。词汇表中包含一些构件和连接件类型,而这组约束指出系统是如何将这些构件和连接件组合起来的。体系结构风格反…...

xss-labs靶场通关详解

文章目录 前言level1level2level3level4level5level6level7level8level9level10level11level12level13level14level15level16level17level18level19&level20 前言 赶着假期结尾的时候,赶紧给自己找点任务做。现在对xss还是一知半解,只是了解个大概&a…...

关于类和接口

类和接口的区别,去除语法层面,谈谈编程层面的意义。 设计原则SOLID: S:单一职责(SRP),Single Responsibility Principle O:开-闭原则(OCP),Open-Closed Principle L:里氏替换(LSP)&…...

网络安全社区与资源分享: 推荐网络安全社区、论坛、博客、培训资源等,帮助从业者拓展人脉和知识。

第一章:引言 在当今数字化的世界中,网络安全问题变得愈发突出。随着各种新型威胁的涌现,网络安全从业者面临着持续不断的挑战。然而,正是因为这些挑战,网络安全社区应运而生,成为从业者们互相交流、学习和…...

SAP MM学习笔记26- SAP中 振替转记(转移过账)和 在库转送(库存转储)5 - 总结

SAP 中在库移动 不仅有入库(GR),出库(GI),也可以是单纯内部的转记或转送。 1,振替转记(转移过账) 具体查看我之前的文章。 SAP MM学习笔记26- SAP中 振替转记&#xff…...

Stable Diffusion WebUI提示词Prompts常用推荐

在Stable Diffusion(以下简称SD)中,提示词是很重要的一部分,写好提示词就能让画图事半功倍,下面介绍一款好用的工具,能很程度上让你更轻松。 他就是sd-webui-prompt-all-in-one 下面将详细介绍的安装以及使用,后面将详细讲解提示词(Prompt)应该如何写提示词才能使画…...

Android 13 Ethernet变更

Android13 有线变更 以太网相关的功能在Android12 和13 网络部分变化是不大的,Android11 到Android 12 网络部分无论是代码存放目录和代码逻辑都是有较多修改的,主要包括以下几个部分 限制了设置有线网参数设置接口方法 新增有线网开启关闭接口方法 新…...

基于单片机的超声波语音测距系统

一、系统方案 超声波具有指向性强,能量消耗缓慢,在介质中传播的距离较远,因而超声波经常用于距离的测量,如测距仪和物位测量仪等都可以通过超声波来实现。利用超声波检测往往比较迅速、方便、计算简单、易于做到实时控制&#xff…...

算法系列-力扣876-求链表的中间节点

# 求链表中间节点,如果有两个中间节点取后面那个 链表定义 // lc codestart /** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode() {} * ListNode(int val) { this.val val; } * …...

SpringBoot集成Redis、Redisson保姆教程【附源码】

1. SpringBoot集成Redis 关于Redis的安装,这里就不重复介绍了,需要的朋友可以看我之前的博文Redis多系统安装(Windows、Linux、Ubuntu) Redis原生命令大全,作者整理的很详细,大部分命令转化为java命令基本也是关键词 Redis 命令参考 接下来开始我们的正题,一起学习下…...

c++多线程中常用的使用方法

1)promise(保证)和future的联合使用&#xff0c;实现两个线程的数据传递 #include <iostream> #include<thread> #include<future>using namespace std;//promise用法&#xff1a;可以给线程一个值&#xff0c;而从另一个线程读出该值 // 实现了两个线程的数…...

【dart】dart基础学习使用(一):变量、操作符、注释和库操作

前言 学习dart语言。 注释 Dart 支持单行注释、多行注释和文档注释。 单行注释 单行注释以 // 开头。Dart 编译器将忽略从 // 到行尾之间的所有内容。 void main() {// 这是单行注释print(Welcome to my Llama farm!); }多行注释 多行注释以 /* 开始&#xff0c;以 / 结…...

element-plus 设置 el-date-picker 弹出框位置

前言 概述&#xff1a;el-date-picker 组件会自动根据空间范围进行选择比较好的弹出位置&#xff0c;但特定情况下&#xff0c;它自动计算出的弹出位置并不符合我们的实际需求&#xff0c;故需要我们手动设置。 存在的问题&#xff1a;element-plus 中 el-date-picker 文档中并…...

C++day7(auto关键字、lambda表达式、C++中的数据类型转换、C++标准模板库(STL)、list、文件操作)

一、Xmind整理&#xff1a; 关键词总结&#xff1a; 二、上课笔记整理&#xff1a; 1.auto关键字 #include <iostream>using namespace std;int fun(int a, int b, float *c, char d, double *e,int f) {return 12; }int main() {//定义一个函数指针&#xff0c;指向fu…...

纽扣电池/锂电池UN38.3安全检测报告

根据规章要求&#xff0c;航空公司和机场货物收运部门应对锂电池进行运输文件审查&#xff0c;重要的是每种型号的锂电池UN38.3安全检测报告。该报告可由的三方检测机构。如不能提供此项检测报告&#xff0c;将禁止锂电池进行航空运输. UN38.3包含产品&#xff1a;1、 锂电池2…...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

多场景 OkHttpClient 管理器 - Android 网络通信解决方案

下面是一个完整的 Android 实现&#xff0c;展示如何创建和管理多个 OkHttpClient 实例&#xff0c;分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

Java 加密常用的各种算法及其选择

在数字化时代&#xff0c;数据安全至关重要&#xff0c;Java 作为广泛应用的编程语言&#xff0c;提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景&#xff0c;有助于开发者在不同的业务需求中做出正确的选择。​ 一、对称加密算法…...

三体问题详解

从物理学角度&#xff0c;三体问题之所以不稳定&#xff0c;是因为三个天体在万有引力作用下相互作用&#xff0c;形成一个非线性耦合系统。我们可以从牛顿经典力学出发&#xff0c;列出具体的运动方程&#xff0c;并说明为何这个系统本质上是混沌的&#xff0c;无法得到一般解…...

Springboot社区养老保险系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;社区养老保险系统小程序被用户普遍使用&#xff0c;为方…...

音视频——I2S 协议详解

I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议&#xff0c;专门用于在数字音频设备之间传输数字音频数据。它由飞利浦&#xff08;Philips&#xff09;公司开发&#xff0c;以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...

python爬虫——气象数据爬取

一、导入库与全局配置 python 运行 import json import datetime import time import requests from sqlalchemy import create_engine import csv import pandas as pd作用&#xff1a; 引入数据解析、网络请求、时间处理、数据库操作等所需库。requests&#xff1a;发送 …...

DeepSeek源码深度解析 × 华为仓颉语言编程精粹——从MoE架构到全场景开发生态

前言 在人工智能技术飞速发展的今天&#xff0c;深度学习与大模型技术已成为推动行业变革的核心驱动力&#xff0c;而高效、灵活的开发工具与编程语言则为技术创新提供了重要支撑。本书以两大前沿技术领域为核心&#xff0c;系统性地呈现了两部深度技术著作的精华&#xff1a;…...

上位机开发过程中的设计模式体会(1):工厂方法模式、单例模式和生成器模式

简介 在我的 QT/C 开发工作中&#xff0c;合理运用设计模式极大地提高了代码的可维护性和可扩展性。本文将分享我在实际项目中应用的三种创造型模式&#xff1a;工厂方法模式、单例模式和生成器模式。 1. 工厂模式 (Factory Pattern) 应用场景 在我的 QT 项目中曾经有一个需…...

使用SSE解决获取状态不一致问题

使用SSE解决获取状态不一致问题 1. 问题描述2. SSE介绍2.1 SSE 的工作原理2.2 SSE 的事件格式规范2.3 SSE与其他技术对比2.4 SSE 的优缺点 3. 实战代码 1. 问题描述 目前做的一个功能是上传多个文件&#xff0c;这个上传文件是整体功能的一部分&#xff0c;文件在上传的过程中…...