谷粒商城实战踩坑笔记-Service循环依赖

文章目录

    • 1. 使用 `@Lazy` 注解
    • 2. 使用 `@PostConstruct` 注解
    • 3,补充循环依赖相关知识
      • 循环依赖的原因
      • 举例说明
    • 4,@Lazy 的工作原理

启动项目失败,原因是出现了循环依赖。

在这里插入图片描述

The dependencies of some of the beans in the application context form a cycle:attrController (field private com.atguigu.gulimall.product.service.AttrService com.atguigu.gulimall.product.controller.AttrController.attrService)↓attrService (field com.atguigu.gulimall.product.service.CategoryService com.atguigu.gulimall.product.service.impl.AttrServiceImpl.categoryService)↓categoryService (field com.atguigu.gulimall.product.service.CategoryBrandRelationService com.atguigu.gulimall.product.service.impl.CategoryServiceImpl.categoryBrandRelationService)
┌─────┐
|  categoryBrandRelationService (field com.atguigu.gulimall.product.service.BrandService com.atguigu.gulimall.product.service.impl.CategoryBrandRelationServiceImpl.brandService)
↑     ↓
|  brandService (field com.atguigu.gulimall.product.service.CategoryBrandRelationService com.atguigu.gulimall.product.service.impl.BrandServiceImpl.categoryBrandRelationService)
└─────┘

一共测试了两种解决方案,都是有效的。

1. 使用 @Lazy 注解

解决思路:通过使用 @Lazy 注解,可以让Spring容器延迟初始化bean,直到真正使用时才创建实例。

在这里插入图片描述

示例代码:

public class BrandServiceImpl extends ServiceImpl<BrandDao, BrandEntity> implements BrandService {@Autowired@Lazyprivate CategoryBrandRelationService categoryBrandRelationService;// ....
}

2. 使用 @PostConstruct 注解

解决思路

  • 这种方式不是@Lazy简单。
  • ServiceA不要自动注入ServiceB,而是提供一个public的setServiceB方法。
  • ServiceB自动注入ServiceA,且提供一个PostConstruct方法,在方法中调用ServiceA的set方法,把自身对象传递给ServiceB

示例代码:

@Service
public class ServiceA {private ServiceB serviceB;public void setServiceB(ServiceB serviceB) {this.serviceB = serviceB;}
}@Service
public class ServiceB {@Autowiredprivate ServiceA serviceA;@PostConstructpublic void setServiceB() {this.serviceA.setServiceB(this);}
}

3,补充循环依赖相关知识

循环依赖是在软件开发中常见的问题之一,特别是在使用依赖注入(DI)框架时,如Spring框架。

循环依赖指的是两个或多个类互相依赖对方的情况,这可能导致对象无法正确初始化。

循环依赖的原因

  1. 设计问题

    • 过度耦合:当两个类之间存在过多的耦合时,它们可能会形成循环依赖。例如,两个类都试图通过构造函数注入对方的实例。
    • 职责不清:如果两个类之间的职责划分不明确,可能会导致它们之间存在不必要的依赖关系。
  2. 依赖注入问题

    • 构造函数注入:当两个类都试图通过构造函数注入对方时,如果没有适当处理,会导致循环依赖。
    • 静态初始化:如果两个类在静态初始化块中互相引用,也可能产生循环依赖。
  3. 配置问题

    • 配置错误:在配置文件或配置类中错误地设置了依赖关系,可能会无意中引入循环依赖。
    • 懒加载未正确配置:如果没有正确使用懒加载特性(如Spring框架中的@Lazy注解),可能会导致循环依赖。

举例说明

假设我们有两个类 ClassAClassB,它们互相依赖对方:

@Service
public class ClassA {private final ClassB b;public ClassA(ClassB b) {this.b = b;}public void doSomething() {System.out.println("ClassA doing something...");}
}@Service
public class ClassB {private final ClassA a;public ClassB(ClassA a) {this.a = a;}public void doSomething() {System.out.println("ClassB doing something...");}
}

在这种情况下,当Spring容器尝试创建 ClassA 实例时,它需要 ClassB 的实例。而 ClassB 的实例又需要 ClassA 的实例。这形成了一个循环依赖,导致Spring容器无法创建这两个类的实例。

4,@Lazy 的工作原理

@Lazy 注解告诉Spring容器延迟初始化一个bean,直到该bean第一次被请求时才创建其实例。

  1. 元数据解析

    • 当Spring容器启动时,它会扫描所有的配置类和bean定义,解析元数据。
    • 如果一个bean定义上有 @Lazy 注解,那么Spring会识别出这是一个需要懒加载的bean。
  2. 代理机制

    • Spring使用代理机制来实现懒加载。对于需要懒加载的bean,Spring不会立即创建其实例,而是创建一个代理对象(Proxy)。
    • 这个代理对象实现了目标bean的所有接口,并且可以拦截对目标bean的访问。
  3. 代理对象的行为

    • 当第一次尝试访问一个懒加载的bean时,Spring会通过代理对象检测到这个访问请求。
    • 代理对象会检查是否已经创建了目标bean的实例。
    • 如果尚未创建实例,代理对象会触发bean的初始化过程,创建实例并将其实例化结果缓存起来。
    • 如果已经创建了实例,则直接返回已缓存的实例。
  4. 初始化时机

    • 懒加载的bean会在第一次被请求时初始化,而不是在Spring容器启动时初始化。
    • 初始化过程包括注入依赖、调用初始化方法(如 @PostConstruct 标记的方法)等。

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

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

相关文章

PP 6 成本中心 活动类型 以及两者的关联

成本中心创建&#xff1a;KS01 保存即可 活动类型&#xff1a;KL01 &#xff08;有准备&#xff0c;机器&#xff0c;工时等&#xff09; 保存 KP26:活动类型和成本中心的关联

如何在Net8.0平台下开发AOT项目,项目实战分析

1. 前言 前面的文章我们讨论过什么是AOT&#xff0c;以及AOT适用于什么场景&#xff0c; dotnet开发编译之争&#xff1a;Ahead-of-Time(AOT) vs Just-in-Time(JIT)谁才是未来最佳编译选择&#xff1f;&#xff0c;那么如何在Net8.0平台下开发AOT项目。 2. 先决条件 在安装的…

搞懂数据结构与Java实现

文章链接&#xff1a;搞懂数据结构与Java实现 (qq.com) 代码链接&#xff1a; Java实现数组模拟循环队列代码 (qq.com) Java实现数组模拟栈代码 (qq.com) Java实现链表代码 (qq.com) Java实现哈希表代码 (qq.com) Java实现二叉树代码 (qq.com) Java实现图代码 (qq.com)

【讲解下ECMAScript和JavaScript之间有何区别?】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

swagger-ui.html报错404

问题1&#xff1a;权限受限无法访问 由于采用的Shiro安全框架&#xff0c;需要在配置类ShiroConfig下的Shiro 的过滤器链放行该页面&#xff1a;【添加&#xff1a;filterChainDefinitionMap.put("/swagger-ui.html", "anon");】 public ShiroFilterFact…

C# dataGridView 去掉左边多出来空列

1.问题 在使用winform做界面程序时&#xff0c;dataGridView控件创建好后&#xff0c;左侧会多出一列为空&#xff0c;如何删除呢 2.解决方法 你可以在属性窗口中进行设置 如图&#xff1a; 将RowHeadersVisible 属性设置为False 或者代码设置 this.dataGridView1.RowHea…

算力共享:如何理解、标识与调控多层次算力资源的异构性和复杂性,实现智能算力网生态诸要素有效互操作?

目录 鹏程云主机和NPU计算服务器关系 NPU计算服务器 两者关系 结论 两种不同类型的处理器或计算单元 FPGA MLU NS3(Network Simulator version 3) 一、基本属性 二、主要功能与特点 三、应用与前景 对象存储和HDD存储 一、定义与特点 二、应用场景 三、总结 对…

基于深度学习网络的USB摄像头实时视频采集与水果识别matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 (完整程序运行后无水印) 将usb摄像头对准一个播放不同水果图片的显示器&#xff0c;然后进行识别&#xff0c;识别结果如下&#xff1a; 本课题中…

【2025留学】德国留学真的很难毕业吗?为什么大家不来德国留学?

大家好&#xff01;我是德国Viviane&#xff0c;一句话讲自己的背景&#xff1a;本科211&#xff0c;硕士在德国读的电子信息工程。 之前网上一句热梗&#xff1a;“德国留学三年将是你人生五年中最难忘的七年。”确实&#xff0c;德国大学的宽进严出机制&#xff0c;延毕、休…

PHP多场地预定小程序系统源码

一键畅游多地&#xff01;多场地预定小程序的超实用指南 段落一&#xff1a;【开篇&#xff1a;告别繁琐&#xff0c;预订新体验】 &#x1f389;&#x1f680; 还在为多个活动或会议的场地预订而头疼不已吗&#xff1f;多场地预定小程序来拯救你啦&#xff01;它像是一位贴心…

基于Element UI内置的Select下拉和Tree树形组件,组合封装的树状下拉选择器

目录 简述 效果 功能描述 代码实现 总结 简述 基于Element UI内置的Select下拉和Tree树形组件&#xff0c;组合封装的树状下拉选择器。 效果 先看效果&#xff1a; 下拉状态&#xff1a; 选择后状态&#xff1a; 选择的数据&#xff1a; 功能描述 1、加载树结构&…

FastAPI(七十八)实战开发《在线课程学习系统》接口开发-- 评论

源码见&#xff1a;"fastapi_study_road-learning_system_online_courses: fastapi框架实战之--在线课程学习系统" 梳理下思路 1.判断是否登录 2.课程是否存在 3.如果是回复&#xff0c;查看回复是否存在 4.是否有权限 5.发起评论 首先新增pydantic模型 class Cour…

Git勤勉 两种方式上传

官网 勤勉Gitea 创建仓库 上传代码 可以先取个仓库名字 给个分支的名字就可以创建了 创建好了会出现一个链接 复制这个链接 打开要上传的项目 删除.idea/target/iml文件 cmd打开小黑窗 输入这个命令 初始化 添加仓库缓存 git init git xxx 把刚刚复制的链接放上去 gi…

【深度学习】大模型GLM-4-9B Chat ,微调与部署(3) TensorRT-LLM、TensorRT量化加速、Triton部署

文章目录 获取TensorRT-LLM代码&#xff1a;构建docker镜像并安装TensorRT-LLM&#xff1a;运行docker镜像&#xff1a;安装依赖魔改下部分package代码&#xff1a;量化&#xff1a;构建图&#xff1a;全局参数插件配置常用配置参数 测试推理是否可以代码推理CLI推理 性能测试小…

pyqt designer使用spliter

1、在designer界面需要使用spliter需要父界面不使用布局&#xff0c;减需要分割两个模块选中&#xff0c;再点击spliter分割 2、在分割后&#xff0c;再对父界面进行布局设置 3、对于两边需要不等比列放置的&#xff0c;需要套一层 group box在最外层进行分割

从善如流之您最亲近人之善,肯出力之象-下学而上达

您最亲近人之善&#xff0c;肯出力之象&#xff0c;就是那个爬&#xff0c;甚至于跪倒在地上&#xff0c;抹那个下水井子。这或许就是那个马云大佬讲过的&#xff0c;就是从您最近距离&#xff0c;身边的人学习。人家为啥做的好&#xff0c;出色&#xff1f;而且您是一母同胞之…

基于微信小程序+SpringBoot+Vue的网络安全科普系统(带1w+文档)

基于微信小程序SpringBootVue的网络安全科普系统(带1w文档) 基于微信小程序SpringBootVue的网络安全科普系统(带1w文档) 优质的网络安全科普系统不仅可以单纯的满足工作人员管理的日常工作需求&#xff0c;还可以满足用户的需求。可以降低工作人员的工作压力&#xff0c;提高效…

LeetCode刷题笔记第682题:棒球比赛

LeetCode刷题笔记第682题&#xff1a;棒球比赛 题目&#xff1a; 想法&#xff1a; 遍历输入的列表&#xff0c;按照规则将分数和操作依次进行&#xff0c;存储在新建的列表中&#xff0c;最终输出列表中的元素和&#xff0c;代码如下&#xff1a; class Solution:def calPo…

网安零基础入门神书,全面介绍Web渗透核心攻击与防御方式!

Web安全是指Web服务程序的漏洞&#xff0c;通常涵盖Web漏洞、操作系统洞、数据库漏洞、中间件漏洞等。 “渗透测试”作为主动防御的一种关键手段&#xff0c;对评估网络系统安全防护及措施至关重要&#xff0c;因为只有发现问题才能及时终止并预防潜在的安全风险。 根据网络安…

第6篇文献研读生态廊道相关综述

该文发在生态与农村环境学报。该文章写了生态廊道概念的发展历程、生态廊道类型及功能、生态廊道划定的理论和方法、生态廊道的时间和国内大型生态廊道建设实践。 这篇文章可以让大家了解生态廊道的知识。