Spring boot 交叉引用问题随机出现

问题描述

我在构建 Spring Boot 项目时遇到了循环依赖(交叉引用)问题,并且依赖趋势如下:

The dependencies of some of the beans in the application context form a cycle:
   app
┌─────┐
|  XXXProcessor defined in file ...
↑     ↓
|  XXXCriteria defined in file ...
↑     ↓
|  XXXCacheManager
↑     ↓
|  XXXRuleSet defined in file ...
└─────┘

虽然我可以努力从 RuleSet 类中删除 Processor 的依赖项,但我想知道是否有一种方法可以保留当前引用但仍然消除此处介绍的交叉引用问题?我查了一下这个论坛,有人建议 @Lazy 注释可能会有所帮助。我尝试将其应用于 Processor 类或 RuleSet 类(在类级别或方法级别),但问题并未消失。

一个观察结果是,上面引用的错误并不是一直出现 - 有时程序运行得很好,是随机出现的错误让我烦恼。为什么会这样?

解决方法

您可以在一处用字段注入替换构造函数注入。它将打破循环对象实例化的循环。

很难说为什么会不时发生这个问题。也许,有一些 2021-04-26 08:59:592021-04-26T15:59:59Z [Debug] Shutdown Initiated. Current epoch in nanoseconds: 1619452799073953600 2021-04-26 08:59:592021-04-26T15:59:59Z [Info] Got shutdown signal: terminated 2021-04-26 08:59:592021-04-26T15:59:59Z [Debug] Skipped telemetry data as no segments found 2021-04-26 08:59:592021-04-26T15:59:59Z [Debug] telemetry: done! 2021-04-26 08:59:592021-04-26T15:59:59Z [Debug] Segment batch: done! 2021-04-26 08:59:592021-04-26T15:59:59Z [Debug] Segment batch: done! 2021-04-26 08:59:592021-04-26T15:59:59Z [Debug] Segment batch: done! 2021-04-26 08:59:592021-04-26T15:59:59Z [Debug] Segment batch: done! 2021-04-26 08:59:592021-04-26T15:59:59Z [Debug] Segment batch: done! 2021-04-26 08:59:592021-04-26T15:59:59Z [Debug] Segment batch: done! 2021-04-26 08:59:592021-04-26T15:59:59Z [Debug] Segment batch: done! 2021-04-26 08:59:592021-04-26T15:59:59Z [Debug] Segment batch: done! 2021-04-26 08:59:592021-04-26T15:59:59Z [Debug] processor: done! 2021-04-26 08:59:592021-04-26T15:59:59Z [Debug] Trace segment: received: 0,truncated: 0,processed: 0 2021-04-26 08:59:592021-04-26T15:59:59Z [Debug] Shutdown finished. Current epoch in nanoseconds: 1619452799074286437 2021-04-26 08:59:582021-04-26T15:59:58Z [Info] Starting proxy http server on 0.0.0.0:2000 2021-04-26 08:59:582021-04-26T15:59:58Z [Error] Get instance id metadata failed: RequestError: send request failed 2021-04-26 08:59:58caused by: Get http://169.254.169.254/latest/meta-data/instance-id: dial tcp 169.254.169.254:80: connect: invalid argument 2021-04-26 08:59:582021-04-26T15:59:58Z [Debug] Using Endpoint: https://xray.us-east-1.amazonaws.com 2021-04-26 08:59:582021-04-26T15:59:58Z [Debug] Telemetry initiated 2021-04-26 08:59:582021-04-26T15:59:58Z [Info] HTTP Proxy server using X-Ray Endpoint : https://xray.us-east-1.amazonaws.com 2021-04-26 08:59:582021-04-26T15:59:58Z [Debug] Using Endpoint: https://xray.us-east-1.amazonaws.com 2021-04-26 08:59:582021-04-26T15:59:58Z [Debug] Batch size: 50 2021-04-26 08:59:572021-04-26T15:59:57Z [Debug] Get hostname metadata failed: RequestError: send request failed 2021-04-26 08:59:57caused by: Get http://169.254.169.254/latest/meta-data/hostname: dial tcp 169.254.169.254:80: connect: invalid argument 2021-04-26 08:59:572021-04-26T15:59:57Z [Debug] Using proxy address: 2021-04-26 08:59:572021-04-26T15:59:57Z [Debug] Fetch region us-east-1 from environment variables 2021-04-26 08:59:572021-04-26T15:59:57Z [Info] Using region: us-east-1 2021-04-26 08:59:572021-04-26T15:59:57Z [Debug] ARN of the AWS resource running the daemon: 2021-04-26 08:59:572021-04-26T15:59:57Z [Info] Initializing AWS X-Ray daemon 3.2.0 2021-04-26 08:59:572021-04-26T15:59:57Z [Debug] Listening on UDP 0.0.0.0:2000 2021-04-26 08:59:572021-04-26T15:59:57Z [Info] Using buffer memory limit of 37 MB 2021-04-26 08:59:572021-04-26T15:59:57Z [Info] 592 segment buffers allocated 类根据配置值构建相同接口的不同实现。您应该提供更多详细信息来处理此问题。

,

解决此问题的一种方法是将一个实例替换为 Provider,如下所示:

public Processor(Provider<Criteria> criteria) {
    this.criteria = criteria;
}

然后在使用时需要先get()

Criteria c = this.criteria.get();

这意味着 Processor 可以在 Criteria 之前构造,因为注入的 Provider 一旦准备好将获得 Criteria bean。

这意味着您不能在构造函数中调用 get() 否则您将收到运行时错误,因为这仍然意味着循环构造依赖。

@Lazy 只是意味着 Spring 应该等待初始化 bean 直到它被实际请求,而不是在启动时急切地创建它(这是标准行为)。这对循环依赖项和注入其他 bean 构造函数的 bean 的影响为零。对于初始化非常慢并且必须几乎总是从 Provider 使用以实际延迟初始化的 bean 很有用。