Java项目中启动报错循环依赖问题解决

createh52周前 (03-04)技术教程5

项目启动时候失败,有时候经常看到这样的错误信息:

Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: 
Error creating bean with name 'liveRoomServiceImpl': Bean with name 'liveRoomServiceImpl' 
has been injected into other beans [rongCouldMsgService] 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 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.

出现类似的情况,说明就是循环依赖所导致的了。

常见的会导致循环依赖出现的编程方式

项目中常见的就是service层那一块会出现错误的引用方式导致出现循环依赖:

项目中存在bean自己引用自己的情况

@Service
public class TestServiceImpl implements TestService {
 Logger logger = LoggerFactory.getLogger(TestServiceImpl.class);
 @Autowired
 TestService testService;
 @0verride
 @Async
 public void test(){
     System. out.println(1122) ;
 }
}


项目serviceA引用serviceB,serviceB中有引用serviceA的情况

@Service
public class LiveAttentionServiceImpl extends BaseService implements LiveAttentionService {

    @Autowired
    private LivePanelService livePanelService;
}
public class LivePanelServiceImpl implements LivePanelService {

    @Autowired
    private LiveAttentionService liveAttentionService;

}

以上这两种写法都会导致循环依赖的问题,最终导致在项目中启动时候出现如上错误信息。

解决方案

Spring循环引用报错,目前没有很好的解决方案

in its raw version as part of a circular reference, but has eventually been wrapped.

循环依赖Spring是解决的,得益于spring的内部机制,让我们根本无法感知它有问题,因为spring默默帮我们解决了,使用的是内部有三级缓存:

  • singletonObjects 一级缓存,用于保存实例化、注入、初始化完成的bean实例
  • earlySingletonObjects 二级缓存,用于保存实例化完成的bean实例singletonFactories
  • 三级缓存,用于保存bean创建工厂,以便于后面扩展有机会创建代理对象。

但是为什么还会出现呢?可能是循环依赖写法导致Spring三级缓存也没法注入正确导致。有如何解决方案。

1. 使用@Lazy注解,延迟加载进行解决

@Lazy注解的功能是,在Spring 在启动的时候延迟加载这个bean,然后在他即调用这个bean的时候再去初始化,这样就避免了Spring循环引用的异常。

2. 避免这种写法

业务中非得使用ServiceA注入ServiceB,ServiceB中注入ServiceA的业务场景,则抽取出来一个ServiceAB类,在ServiceAB中注入ServiceA和ServiceB

3. 使用SpringUtils工具类获取实例化循环依赖的Bean

和@Lazy有异曲同工之处

循环依赖原因

相关文章

Java:Spring用三级缓存解决循环依赖问题

缓存其实就是三个Map容器:singletonObjects, 一级缓存;earlySingletonObjects, 二级缓存;singletonFactories 三级缓存。如下图例如:A引用B...

大厂面试必问之Spring的循环依赖

面试的重点,大厂必问之一:循环依赖1. 什么是循环依赖看下图image.png??上图是循环依赖的三种情况,虽然方式有点不一样,但是循环依赖的本质是一样的,就你的完整创建要依赖与我,我的完整创建也依赖...

彻底搞懂Spring依赖注入(一)Bean实例创建过程

上一章介绍了Bean的加载过程(IOC初始化过程),加载完成后,紧接着就要用到它的依赖注入(IOC 依赖注入)。那什么是依赖注入呢?所谓依赖注入,就是由IOC容器在运行期间,动态地将某种依赖关系注入到...

Spring之IOC&依赖注入

0x01、Spring1什么是Spring Spring 是一个开源框架,是为了解决企业应用程序开发复杂性而创建的(解耦)。? 框架的主要优势之一就是其分层架构,分层架构允许您选择使用哪一个组件,同时...

手把手教你解决循环依赖,一步一步地来窥探出三级缓存的奥秘

先不去管Spring中的循环依赖,我们先实现一个自定义注解,来模拟@Autowired的功能。一、自定义注解模拟@Autowired自定义Load注解,被该注解标识的字段,将会进行自动注入/** *...