相信很多做过Java SpringBoot项目的人都会遇过循环依赖的问题。
循环依赖产生的原因
循环依赖的本质是两个服务的职责边界不清晰,或直接依赖了对方的完整实例。
举个例子:
UserOrgRelationService
java
package com.example.druidtest.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
* @author chenshixian
**/
@Service
public class UserOrgRelationService {
@Autowired
private UserService userService;
@Autowired
private OrgService orgService;
// 公共逻辑:根据用户ID查所属机构、根据机构ID查用户列表等
public List<Long> getOrgIdsByUserId(Long userId) {
// 实现查询逻辑
return new ArrayList<>();
}
public List<Long> getUserIdsByOrgId(Long orgId) {
// 实现查询逻辑
return new ArrayList<>();
}
public void addUserOrgRelation(Long userId, Long orgId) {
if (userService.getUserById(userId) == null) {
throw new RuntimeException("用户不存在");
}
if (orgService.getOrgById(orgId) == null) {
throw new RuntimeException("用户不存在");
}
}
}
java
// 2. 用户服务:依赖公共组件,不再直接依赖机构服务
@Service
public class UserService {
@Autowired
private UserOrgRelationService userOrgRelationService;
// 用户服务的核心逻辑
public User getUserById(Long userId) {
// 如需机构相关数据,调用公共组件
List<Long> orgIds = userOrgRelationService.getOrgIdsByUserId(userId);
// 其他逻辑
return new User();
}
}
// 3. 机构服务:依赖公共组件,不再直接依赖用户服务
@Service
public class OrgService {
@Autowired
private UserOrgRelationService userOrgRelationService;
// 机构服务的核心逻辑
public Org getOrgById(Long orgId) {
// 如需用户相关数据,调用公共组件
List<Long> userIds = userOrgRelationService.getUserIdsByOrgId(orgId);
// 其他逻辑
return new Org();
}
}
这个时候 ,后台就会报循环依赖:

这里UserOrgRelationService依赖了UserService和OrgService,而UserService又依赖了UserOrgRelationService,就产生了循环依赖。
解决方案
1. 逻辑分拆
这里可以逻辑都加载UserService里面。
java
package com.example.druidtest.service;
import com.example.druidtest.entity.Org;
import com.example.druidtest.entity.User;
import com.example.druidtest.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @author chenshixian
**/
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Autowired
private UserOrgRelationService userOrgRelationService;
@Autowired
private OrgService orgService;
// 用户服务的核心逻辑
public User getUserById(Long userId) {
// 如需机构相关数据,调用公共组件
List<Long> orgIds = userOrgRelationService.getOrgIdsByUserId(userId);
// 其他逻辑
return new User();
}
public void addUser(User user, Long orgId) {
userRepository.save(user);
Org org = orgService.getOrgById(orgId);
if (org != null) {
throw new RuntimeException("机构不存在");
}
userOrgRelationService.add(user.getId(), orgId);
}
}
方案 2:使用 Spring 上下文延迟获取 Bean(应急方案)
如果暂时无法拆分逻辑,可以通过 ApplicationContext 延迟获取依赖的 Bean,打破初始化阶段的循环依赖(本质是 "懒加载",而非真正解耦)。
示例实现:
@Service
public class UserService {
// 注入Spring上下文
@Autowired
private ApplicationContext applicationContext;
// 业务方法中延迟获取机构服务
public void doUserBiz(Long userId) {
// 不在初始化阶段获取,而是在使用时获取
OrgService orgService = applicationContext.getBean(OrgService.class);
orgService.queryOrgByUserId(userId);
// 其他业务逻辑
}
}
@Service
public class OrgService {
@Autowired
private ApplicationContext applicationContext;
public void doOrgBiz(Long orgId) {
UserService userService = applicationContext.getBean(UserService.class);
userService.queryUserByOrgId(orgId);
// 其他业务逻辑
}
}
方案 3:使用 @Lazy 懒加载(适用于构造器注入场景)
如果必须使用构造器注入(Spring 推荐的注入方式),可以通过 @Lazy 注解让依赖的 Bean 延迟初始化,避免初始化阶段的循环依赖。
示例实现:
@Service
public class UserService {
private final OrgService orgService;
// 构造器注入时添加@Lazy,延迟加载OrgService
public UserService(@Lazy OrgService orgService) {
this.orgService = orgService;
}
public void queryUserByOrgId(Long orgId) {
// 业务逻辑
}
}
@Service
public class OrgService {
private final UserService userService;
// 同理,延迟加载UserService
public OrgService(@Lazy UserService userService) {
this.userService = userService;
}
public void queryOrgByUserId(Long userId) {
// 业务逻辑
}
}
方案 4:使用 setter 注入(Spring 原生支持)
Spring 对单例 Bean 的 setter 注入天然支持循环依赖(通过三级缓存解决),这是最基础的解决方案,但可读性和规范性不如前几种。
示例实现:
@Service
public class UserService {
private OrgService orgService;
// setter注入(而非构造器/字段注入)
@Autowired
public void setOrgService(OrgService orgService) {
this.orgService = orgService;
}
// 业务方法
public void doBiz() {
orgService.queryOrg();
}
}
@Service
public class OrgService {
private UserService userService;
@Autowired
public void setUserService(UserService userService) {
this.userService = userService;
}
// 业务方法
public void queryOrg() {
// 逻辑
}
}