解决循环依赖问题:优雅处理依赖关系的技巧

简介: 在软件开发中,依赖是不可避免的。我们经常需要在应用程序的不同组件之间建立依赖关系,以实现功能的模块化和复用。然而,有时候依赖关系可能变得复杂,甚至导致循环依赖的问题。在本文中,我们将通过项目中实际遇到的异常探讨一些解决循环依赖问题的技巧,帮助你在开发过程中优雅地处理依赖关系。

-2023-06-27-2017-2.png

在软件开发中,依赖是不可避免的。我们经常需要在应用程序的不同组件之间建立依赖关系,以实现功能的模块化和复用。然而,有时候依赖关系可能变得复杂,甚至导致循环依赖的问题。在本文中,我们将通过项目中实际遇到的异常探讨一些解决循环依赖问题的技巧,帮助你在开发过程中优雅地处理依赖关系。

异常详情

Spring Bean配置中存在循环依赖的问题。具体而言,名为'mngAuditWorkbenchSummaryRepositoryImpl'的Bean已经注入到其他多个Bean中,但Spring无法解决这个循环引用。

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'myCardService': Unsatisfied dependency expressed through field 'workRepository'; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'mngAuditRepositoryImpl': Bean with name 'mngAuditRepositoryImpl' has been injected into other beans [zwInfoServiceImpll] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:643)
        at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119)
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1420)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:593)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516)
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda{
   
   mathJaxContainer[0]}0(AbstractBeanFactory.java:324)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:897)
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:879)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:551)
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141)
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747)
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:405)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215)
        at cn.xj.CMCCApplication.main(CMCCApplication.java:31)
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'mngAuditRepositoryImpl': Bean with name 'mngAuditRepositoryImpl' has been injected into other beans [zwInfoServiceImpl] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:623)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516)
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda{
   
   mathJaxContainer[1]}0(AbstractBeanFactory.java:324)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
        at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1307)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1227)
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:640)
异常说明

错误信息表明在你的Spring Bean配置中存在循环依赖的问题。具体而言,名为'mngAuditWorkbenchSummaryRepositoryImpl'的Bean已经注入到其他多个Bean中,但Spring无法解决这个循环引用。

循环依赖发生在两个或多个Bean直接或间接地相互依赖,创建了一个无法由Spring解决的循环。

解决方案
  • 分析依赖关系:确定涉及循环引用的Bean,并确定它们之间的依赖关系。了解依赖关系图有助于找到解决方案。

  • 打破循环依赖:有几种方法可以打破循环依赖。以下是一些常见的方法:

    • 构造函数注入:考虑使用构造函数注入而不是字段或setter注入。这样可以在对象创建时解决依赖关系。
    • 使用@Autowired的setter注入:使用setter注入和@Autowired注解,同时在setter方法上添加@Autowired注解。然后,通过setter方法设置必要的依赖项,而不是字段注入。
    • 使用基于接口的代理:如果可能,为涉及的Bean引入接口,并使用基于接口的代理来解决循环依赖。
  • 重新审查设计:循环依赖通常是设计问题的指示。请考虑审查应用程序的架构,并查看是否有机会进行重构或解耦相关的Bean。

  • 使用延迟初始化:你可以尝试对循环引用中的一个或多个Bean使用延迟初始化。可以通过使用@Lazy注解来配置这些Bean。

  • 使用getBeanNamesForType:不要使用自动装配,而是使用getBeanNamesForType方法,并将allowEagerInit标志设置为false。这可以帮助你识别涉及循环引用的Bean,并手动解决依赖关系。

我们在实际项目中使用的使用延迟初始化 的方法,代码如下:

@Service
@Lazy
public class workRepository {
   
   
    //业务代码
}
总结

解决循环依赖问题需要细心分析依赖关系,并采取适当的措施来解决问题。选择合适的方法取决于具体的情况和使用的技术栈。在实施任何更改之前,确保进行充分的测试

目录
相关文章
Idea在debug时打上断点没有用 Skipped breakpoint at ... because it happened inside debugger evaluation
Idea在debug时打上断点没有用 Skipped breakpoint at ... because it happened inside debugger evaluation
2856 0
|
5月前
|
缓存 NoSQL Java
Java Redis 面试题集锦 常见高频面试题目及解析
本文总结了Redis在Java中的核心面试题,包括数据类型操作、单线程高性能原理、键过期策略及分布式锁实现等关键内容。通过Jedis代码示例展示了String、List等数据类型的操作方法,讲解了惰性删除和定期删除相结合的过期策略,并提供了Spring Boot配置Redis过期时间的方案。文章还探讨了缓存穿透、雪崩等问题解决方案,以及基于Redis的分布式锁实现,帮助开发者全面掌握Redis在Java应用中的实践要点。
317 6
|
Java 测试技术 开发者
循环依赖:解析软件设计的迷局
循环依赖:解析软件设计的迷局
|
人工智能 Java 测试技术
JDK11下Mock框架进化:从PowerMockito到Mockito Only
本文探讨了从使用PowerMock的测试环境迁移到仅使用Mockito(Mockito Only)策略的必要性和实践方法。
544 10
|
SQL XML 缓存
认识 ORM 框架 Hibernate,为什么 2022 年了还在谈论它?
前言 Hibernate 作为一种全自动 ORM 框架,在几年前常与 Spring、Struts2 一起使用,并称 SSH,作为主流的企业级应用框架。伴随着 MyBatis 的诞生,以及 Hibernate 本身的一些缺陷,如今 Hibernate 已经慢慢淡出了大家的视野。
1253 0
认识 ORM 框架 Hibernate,为什么 2022 年了还在谈论它?
|
C语言
C语言陷阱——无符号数和有符号数的大小比较
C语言陷阱——无符号数和有符号数的大小比较
|
Web App开发 Java 测试技术
《手把手教你》系列基础篇之(一)-java+ selenium自动化测试-环境搭建(上)(详细教程)
【2月更文挑战第10天】《手把手教你》系列基础篇之(一)-java+ selenium自动化测试-环境搭建(上)(详细教程) jmeter系列的文章结束,本来想趁热打铁顺别将Jmeter和接口测试介绍一下,但是感觉Jmeter时间太长了怕大家吃腻了,还有一个原因就是许多小伙伴们或者童鞋们私信问宏哥什么时候可以有java版的selenium,因为不会Python,或者现在大多数企业和公司还是把java奉在神坛上,所以宏哥打算就换个口味,介绍一下java+ selenium自动化测试。大致和前边的python+selenium自动化测试差不多。基于java和selenium做自动化测试.
399 0
|
SQL 关系型数据库 MySQL
MySQL - 死锁的产生及解决方案
MySQL - 死锁的产生及解决方案
819 0
|
开发框架 Oracle 关系型数据库
基于.net core 开发的轻量级配置中心 - AgileConfig
AgileConfig 是一个基于 .net core 开发的轻量级配置中心,更多的是为了那些分布式、容器化部署的应用能够更加简单的读取、修改配置。秉承轻量化的,部署简单、配置简单、使用简单、学习简单,它只提取了必要的一些功能,并没有像 Apollo 那样复杂且庞大。但是它的功能也已经足够你替换...
1270 0
基于.net core 开发的轻量级配置中心 - AgileConfig