解决 Spring Boot循环依赖 BeanCurrentlyInCreationException

问题描述:

今天使用SpringSecurity做权限控制时,在一顿操作猛如虎后,启动时遇到bug了,报错内容如下:

***************************
APPLICATION FAILED TO START
***************************

Description:

The dependencies of some of the beans in the application context form a cycle:

   securityConfig
      ↓
   userDetailServiceImpl
┌─────┐
|  sysUserService
↑     ↓
|  sysMenuServiceImpl (field com.jidussy.vueadminjava.service.SysUserService com.jidussy.vueadminjava.service.impl.SysMenuServiceImpl.userService)
└─────┘


Action:

Relying upon circular references is discouraged and they are prohibited by default. Update your application to remove the dependency cycle between beans. As a last resort, it may be possible to break the cycle automatically by setting spring.main.allow-circular-references to true.

 

解决思路:

从报错信息不难看出,问题出在依赖注入环节,sysUserService与SysMenuServiceImpl出现了循环依赖的问题,而且下面的sysMenuServiceImpl后面有明确的提示是SysMenuServiceImpl.userService(这里有个细节,依赖注入时使用@Autowired才会有后面的提示<field com.jidussy.vueadminjava.service.SysUserService com.jidussy.vueadminjava.service.impl.SysMenuServiceImpl.userService>,而使用@Resource不会有任何提示,所以遇到这种循环依赖时可以将@Resource替换为@Autowired来加快排查速度)。

 

解决方法:

进入sysMenuServiceImpl找到userService

 

 这里有用到userService的getByUsername方法,红色框框中的就是产生问题的原因所在,蓝色框框中的就是解决方案,将红色框框注释掉,启用蓝色框框中的方法。我们可以不通过userService来获取用户信息,用userMapper就可以避免这个问题了。

如果非得用的话可以使用以下几种方法:

  • 不使用基于构造函数的依赖注入
  • 在字段上使用@Autowired注解,让Spring决定在合适的时机注入。【推荐】
  • 用基于setter方法的依赖注射取代基于构造函数的依赖注入来解决循环依赖。
  • 在@Autowired注解上方加上@Lazy注解(延迟加载)
  • @Lazy
    @Autowired
    private SysUserServiceImpl userService;

     

还有一种方法:

  • 使用SpringContextHolder获取已经存在的bean
  • SysUserServiceImpl  userService= SpringContextHolder.getBean(SysUserServiceImpl .class)

     

 

SpringBoot通过注解componentScan注解,将Bean注入到Spring容器、那么在注入过程中,如遇到这样的问题在将BeanA注入到容器中的过程中:BeanA持有BeanB的引用,BeanB持有BeanC的引用。BeanC持有BeanA的引用、当BeanA注入依赖于BeanC,BeanC又依赖于BeanA。如此循环,就会导致BeanCurrentlyInCreationException异常.

这就是我们常遇见的SpringBoot循环依赖的问题、通常发生在通过构造器创建Bean之间的依赖关系的时候。

 

总结:

循环依赖可以从最底层的类中开始找,例如A依赖B,B依赖C,C又依赖B时,C会排在最下面,然后通过将依赖注入的注解修改为@Autowired来确定关键字。

 

参考链接:https://blog.csdn.net/weixin_45528650/article/details/119794788

posted @ 2022-04-28 08:29  几度失手ya  阅读(839)  评论(0编辑  收藏  举报