[SpringBoot 2.x.x] 循环依赖The dependencies of some of the beans in the application context form a cycle
作者:mmseoamin日期:2024-04-29

SpringBoot 2.x.x 循环依赖

报错信息

***************************
APPLICATION FAILED TO START
***************************
Description:
The dependencies of some of the beans in the application context form a cycle:
   firTestController
┌─────┐
|  userServiceImpl
↑     ↓
|  systemServiceImpl
└─────┘
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.
Disconnected from the target VM, address: '127.0.0.1:55987', transport: 'socket'

问题原因

// IUserService 接口
public interface IUserService {
    void getUserInfo();
}
// UserServiceImpl 类实现 IUserService 接口
@Component
public class UserServiceImpl implements IUserService {
    @Autowired
    private ISystemService systemService;
    @Override
    public void getUserInfo() {
        System.out.println("Get user info");
    }
}
// ISystemService 接口
public interface ISystemService {
    void getSystemInfo();
}
// SystemServiceImpl 类实现 ISystemService 接口
@Component
public class SystemServiceImpl implements ISystemService {
    @Autowired
    private IUserService userService;
    @Override
    public void getSystemInfo() {
        System.out.println("Get system info");
    }
}
// FirTestController 类
@Component
public class FirTestController {
    @Autowired
    private IUserService userService;
}

提供的例子中,存在循环依赖的原因如下:

UserServiceImpl 依赖于 ISystemService 接口,它的字段 systemService 被 @Autowired 注解注入。

SystemServiceImpl 类实现了 ISystemService 接口,它的字段 userService 被 @Autowired 注解注入。

FirTestController 类依赖于 IUserService 接口,它的字段 userService 被 @Autowired 注解注入。

这样,一个循环的依赖链就形成了:

UserServiceImpl 依赖于 ISystemService

SystemServiceImpl 依赖于 IUserService

FirTestController 依赖于 IUserService

当 Spring 容器启动时,它会尝试解析和创建这些 bean。在解析 UserServiceImpl 时,它会注入一个 ISystemService 实例,而这个实例是 SystemServiceImpl。在解析 SystemServiceImpl 时,它会注入一个 IUserService 实例,而这个实例是 UserServiceImpl。这样就形成了一个循环的依赖链,导致 Spring 容器无法成功创建这些 bean,最终抛出循环依赖的异常。

解决方式

   /**
     * 用户 接口层
     */
    private IUserService iUserService;
    @Autowired
    public void setUserService(@Lazy IUserService iUserService) {
        this.iUserService = iUserService;
    }

采用了 @Lazy 注解来解决循环依赖的问题,这是一种有效的方式。通过将 @Lazy 注解添加到 setUserService 方法上,延迟了 IUserService bean 的初始化,避免了在初始化 UserServiceImpl 时立即创建 IUserService bean 导致的循环依赖问题。

在 Spring 中,@Lazy 注解用于指定 bean 是否应该在需要时被延迟初始化。当一个 bean 被标记为 @Lazy 时,它的初始化会被推迟到第一次被注入或使用时。

通过将 @Lazy 注解应用于循环依赖链中的一个 bean,可以打破循环依赖,使得 Spring 能够成功初始化这些 bean。

解决Spring循环依赖的一般原则之一,即延迟初始化。