Skip to content

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

Description

@Hungerdream

环境

  • 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 之间的依赖,从根本上消除循环。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions