【Bug】应用启动失败:RedisCenterImpl 的 @Async 导致与 MachineCenterImpl / AppScrollRestartServiceImpl 的循环依赖无法解析(BeanCurrentlyInCreationException)

Open Beginner friendly
#387 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
80/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Quiet
Tech stack
java, redis, spring-boot
Domain
backend

Research direction

Start with MachineCenterImpl.java:79 and AppScrollRestartServiceImpl.java:72, then inspect the @Async method in RedisCenterImpl.java around line 912. Apply the issue's lazy-injection change at both RedisCenter injection points and build or start the web application with the open profile. Done means startup completes without BeanCurrentlyInCreationException.

Written by the indexing model from the issue text.

Description

环境

  • CacheCloud 3.4(在 main 分支同样可复现)
  • Spring Boot 2.2.9.RELEASE / Spring Framework 5.2.x / Java 8

现象

Web 应用启动即失败,抛出:

org.springframework.beans.factory.BeanCurrentlyInCreationException:
Error creating bean with name 'redisCenter':
Requested bean is currently in creation: Is there an unresolvable circular reference?

根因分析

MachineCenterImplAppScrollRestartServiceImpl 都通过 @Autowired 注入了 RedisCenter 的实现 RedisCenterImpl

关键点:RedisCenterImpl 上存在 @Async 注解的方法(如 findInstancePatternKeys,返回 java.util.concurrent.Future,见 RedisCenterImpl.java:912)。@Async 要求 Spring 在 bean 完全初始化之后才为其生成异步代理(AsyncAnnotationBeanPostProcessor 处理)。

这导致该循环引用无法用 Spring 的“早期引用(early reference)”机制消解:

  • 循环中的其他 bean 拿到的是 redisCenter 的半成品(原始对象),而容器最终放入的是异步代理;
  • 代理必须在 bean 完全创建后才能生成,因此该循环在结构上“无法解析(unresolvable)”。

修复方案

在两个注入点加 @Lazy(注入懒加载代理占位符以打破循环,已验证有效):

cachecloud-web/src/main/java/com/sohu/cache/machine/impl/MachineCenterImpl.java

+import org.springframework.context.annotation.Lazy;
...
     @Autowired
+    @Lazy
     private RedisCenter redisCenter;

cachecloud-web/src/main/java/com/sohu/cache/web/service/impl/AppScrollRestartServiceImpl.java

+import org.springframework.context.annotation.Lazy;
...
     @Autowired
+    @Lazy
     private RedisCenter redisCenter;

main 分支对应行:MachineCenterImpl.java:79AppScrollRestartServiceImpl.java:72

复现步骤

  1. 按官方文档编译部署(profile=open,MySQL 已就绪)
  2. 启动 web 应用
  3. 启动日志即报上述异常

建议

除上述 @Lazy 最小修复外,也可考虑重构 MachineCenterImpl / AppScrollRestartServiceImplRedisCenter 之间的依赖,从根本上消除循环。

Dominant language
HTML
Stars
9k
Forks
2k
PR merge metrics
No merged PRs in 30d

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from sohutv/cachecloud

All issues in sohutv/cachecloud

Similar issues

More Backend & API Design issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.