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

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

-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 {
   
   
    //业务代码
}
总结

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

目录
相关文章
|
11月前
|
关系型数据库 分布式数据库 数据库
基于PolarDB的图分析:保险数据分析实践
本文以公开的保险数据集为例,示例了基于云原生数据库PolarDB上,在保险理赔场景下,执行图查询来发现异常理赔记录和欺诈团伙:例如,查询与欺诈保单有相同理赔病人的其他保单,或者找出欺诈保单的投保人社交关系,以便进行欺诈预警。PolarDB在关系型数据库的基础上,提供了图分析能力,为企业的统一数据管理和分析,提供了强有力的支撑。
|
安全 Java 网络安全
SpringBoot 优雅停止服务的几种方法
SpringBoot 优雅停止服务的几种方法
346 0
|
Linux 数据处理 开发者
R语言如何快速安装R包?常见方法与报错解决方案汇总,适用于Windows、Mac、Linux多平台
R语言如何快速安装R包?常见方法与报错解决方案汇总,适用于Windows、Mac、Linux多平台
|
安全 网络安全 网络虚拟化
【专栏】子网划分是网络管理关键,涉及子网定义、子网掩码作用及意义
【4月更文挑战第28天】子网划分是网络管理关键,涉及子网定义、子网掩码作用及意义。方法包括确定子网数和主机数、选择子网掩码、计算地址范围和分配地址。网络工程师应合理规划、考虑扩展性,避免子网重叠,结合VLAN技术,定期评估优化。实际应用广泛,如企业、数据中心和校园网络。掌握子网划分技巧,能提升网络性能、安全性和管理效率。
338 0
|
Java 测试技术 Spring
什么是循环依赖,如何解决
什么是循环依赖,如何解决
|
C语言
C语言陷阱——无符号数和有符号数的大小比较
C语言陷阱——无符号数和有符号数的大小比较
|
域名解析 移动开发 运维
Nacos 集群部署模式最佳实践
本文介绍了 Nacos 的三种部署模式,并就高可用、可伸缩、易用性等方面对各个模式进行介绍。
13130 43
Nacos 集群部署模式最佳实践
|
存储 分布式计算 大数据
构建与应用大数据环境:从搭建到开发与组件使用的全面指南
构建与应用大数据环境:从搭建到开发与组件使用的全面指南
468 0
|
消息中间件 Java 关系型数据库
Spring事务畅谈 —— 由浅入深彻底弄懂 @Transactional注解(1)
Spring事务畅谈 —— 由浅入深彻底弄懂 @Transactional注解
5053 0
|
SQL 监控 druid
Spring Boot 整合 Druid 指南
Spring Boot 整合 Druid 指南
41465 3
OSZAR »