问题及日志
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2025-05-21 09:05:55.193 DEBUG 1 --- [ main] o.h.c.a.Slf4jFailureAnalysisReporter : Application failed to start due to an exception
org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration': Requested bean is currently in creation: Is there an unresolvable circular reference?
中间日志省略
2025-05-21 09:05:55.194 ERROR 1 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
The dependencies of some of the beans in the application context form a cycle:
dataChangeAdvice defined in URL [jar:file:/inja-demand.jar!/BOOT-INF/classes!/com/inja/demand/record/aspect/DataChangeAdvice.class]
┌─────┐
| org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
↑ ↓
| attachmentLogInterceptor (field private com.inja.demand.record.domain.repository.ChangeLogRepository com.inja.demand.requirement.interceptor.AttachmentLogInterceptor.changeLogRepository)
↑ ↓
| changeLogRepositoryImpl (field private io.choerodon.mybatis.common.BaseMapper io.choerodon.mybatis.service.BaseServiceImpl.mapper)
↑ ↓
| changeLogMapper defined in URL [jar:file:/inja-demand.jar!/BOOT-INF/classes!/com/inja/demand/record/infra/mapper/ChangeLogMapper.class]
└─────┘
问题代码截图
解决方案
使用@Lazy延迟加载
在其中一个依赖项上添加@Lazy注解来打破循环,例如在AttachmentLogInterceptor的字段注入处:
public class AttachmentLogInterceptor {
@Lazy
@Autowired
private ChangeLogRepository changeLogRepository;
}
不建议使用该方案,因为发生循环依赖本质是代码设计不合理,
要从根本上解决问题,重构代码。
重构代码结构
注意不适用本次出现的问题
-
检查是否可以将部分依赖关系改为构造函数注入
import org.springframework.beans.factory.annotation.Autowired; public class AttachmentLogInterceptor implements Interceptor { private final ChangeLogRepository changeLogRepository; // 构造函数注入 @Autowired // 如果只有一个构造函数,可以省略这个注解 public AttachmentLogInterceptor(ChangeLogRepository changeLogRepository) { this.changeLogRepository = changeLogRepository; } // 其他方法保持不变... }
-
考虑将某些通用功能抽离到独立的工具类中
-
检查BaseServiceImpl的mapper注入方式
本次问题解决
根据代码分析,DataChangeAdvice 通过构造函数直接依赖 SqlSessionTemplate 和 MapperHelper,
而 SqlSessionTemplate 的创建依赖 MyBatis 自动配置(MybatisAutoConfiguration),最终形成以下循环链:
DataChangeAdvice → SqlSessionTemplate → MybatisAutoConfiguration → (其他拦截器/组件) → DataChangeAdvice
修改代码:延迟依赖初始化(核心思路)
@Aspect
@Component
@Slf4j
public class DataChangeAdvice {
// 关键点:使用 ObjectProvider 延迟获取 SqlSessionTemplate
private final ObjectProvider<SqlSessionTemplate> sqlSessionTemplateProvider;
private final ObjectProvider<MapperHelper> mapperHelperProvider;
// 构造函数改造:不再直接依赖 SqlSessionTemplate
public DataChangeAdvice(
ObjectProvider<SqlSessionTemplate> sqlSessionTemplateProvider,
ObjectProvider<MapperHelper> mapperHelperProvider
) {
this.sqlSessionTemplateProvider = sqlSessionTemplateProvider;
this.mapperHelperProvider = mapperHelperProvider;
}
// 实际使用时再获取依赖(例如在切面方法中)
@Around("@annotation(yourAnnotation)")
public Object handleDataChange(ProceedingJoinPoint joinPoint) throws Throwable {
SqlSessionTemplate sqlSession = sqlSessionTemplateProvider.getObject(); // 按需获取
MapperHelper helper = mapperHelperProvider.getIfAvailable();
// 业务逻辑...
return joinPoint.proceed();
}
}
相关问题及解释
参考资料
https://blog.youkuaiyun.com/qq_27759825/article/details/129027330