什么是循环依赖

当一个ClassA依赖于ClassB,然后ClassB又反过来依赖ClassA,这就形成了一个循环依赖:

ClassA -> ClassB -> ClassA

原创声明

本文发布于掘金号【Happyjava】。Happy的掘金地址:https://juejin.im/user/5cc2895df265da03a630ddca,Happy的个人博客:(http://blog.happyjava.cn)[http://blog.happyjava.cn]。欢迎转载,但须保留此段声明。

Spring的循环依赖问题

当你使用构造注入依赖的时候,就有可能发生循环依赖然后报错的问题。什么是构造注入呢?可以看如下代码:

假设有ClassA和ClassB如下:

ClassA.java

@Data
@Component
public class ClassA { private final ClassB classB; public ClassA(ClassB classB) {
this.classB = classB;
}
}

ClassB.java

@Data
@Component
public class ClassB { private final ClassA classA; public ClassB(ClassA classA) {
this.classA = classA;
}
}

就是在类的构造方法里,把依赖注入,这就是所说的构造注入。

构造注入,也是Spring团队推荐的Spring依赖注入的方式(依赖来自IDEA的提示):

虽然是Spring的官方推荐,但是这种方式就是容易出现循环依赖导致程序跑不起来的情况:

当然,也存在多种解决循环依赖的办法,下面一一演示。

重新设计代码

当出现循环依赖的时候,可以考虑重新设计下代码。一般来说,当循环依赖问题出现的时候,往往其原因是设计上分层没有处理好,各个类的耦合度高,各自的职责不够单一。

当然,很多时候,我们也没有那么多时间去重新设计代码。那么,我们可以采取别的方式。

使用懒加载

可以通过Spring提供的@Lazy注解,让Spring懒加载,即当真正需要使用到该bean的时候,再去加载。如,我给上面的示例代码的ClassB的构造方法加入@Lazy注解:

@Data
@Component
public class ClassB { private final ClassA classA; public ClassB(@Lazy ClassA classA) {
this.classA = classA;
}
}

再次启动,就会发现循环依赖报错问题不存在了。

直接使用Autowired单独注入

直接使用@Autowired注入依赖,不要使用构造器的方式注入

@Data
@Component
public class ClassB { @Autowired
private ClassA classA; }
@Data
@Component
public class ClassA { @Autowired
private ClassB classB; }

这种方式,也可以解决Spring循环依赖的问题。

使用Setter注入

除了以上两种方式,还可以通过setter的方式来注入依赖。如下:

ClassA.class

@Data
@Component
public class ClassA { private ClassB classB; @Autowired
public void setClassB(ClassB classB) {
this.classB = classB;
}
}

ClassB.class

@Data
@Component
public class ClassB { private ClassA classA; @Autowired
public void setClassA(ClassA classA) {
this.classA = classA;
}
}

通过Setter注入依赖的方式,一样可以解决Spring循环依赖的问题。

总结

使用Spring作为开发框架,一不小心就会碰到循环依赖,程序启动不了的问题。如果真的出现了循环依赖的问题,可以尝试采用上面的几种方式解决。当然,解决的办法还有很多,比如,还可以通过PostConstruct注解来解决(摘抄baeldung的博客):

方法可能有很多种,就不太深入探讨了。

关注公众号领资料

搜索公众号【Happyjava】,回复【电子书】和【视频】,即可获取大量优质电子书和大数据、kafka、nginx、MySQL等视频资料

最新文章

  1. jquery中ajax用return来返回值无效
  2. 王爽<汇编语言>实验十
  3. 我也想聊聊 OAuth 2.0 —— 基本概念
  4. (18)odoo规范
  5. js中的cookie使用
  6. SQL语句执行顺寻
  7. 阿里巴巴笔试整理系列 Session2 高级篇
  8. hdu 4502吉哥系列故事——临时工计划 (简单DP)
  9. SQLServer 索引总结
  10. 利用idea解决git代码冲突问题
  11. faster-rcnn 笔记
  12. inux下配置rsyncd服务
  13. Linux虚拟内存的添加
  14. asp.net:如何实现负载均衡方案讨论 (nginx+iis实现负载均衡)
  15. [LeetCode系列] 双单链表共同节点搜索问题
  16. JS——图片预览功能
  17. 分类Category的概念和使用流程
  18. HDU 2577 分情况多维DP
  19. vmware虚拟机安装CentOS教程
  20. TCP的发送缓冲区和接收缓冲区

热门文章

  1. vue简单计数器
  2. PHP获取用户的真实IP地址,非代理IP
  3. 树莓派4B踩坑指南 - (11)免费搭建网站(宝塔,花生壳)
  4. spark-shell中往mysql数据库写数据报错
  5. Docker - 解决docker-machine create下载boot2docker.iso时慢的问题
  6. JS高级---体会面向对象和面向过程的编程思想
  7. RS422接口与RS485接口
  8. MAC记住 git的用户名密码
  9. Linux Mysql8每天定时备份数据库并自动删除7天之前的备份
  10. java8date