为什么使用 CDI 进行自我注入不会导致无限循环?

Why does self injection with CDI not result in an infinite loop?

为什么这个建筑有效?

@Stateless
public class SomeClass {

    @Inject
    private SomeClass self;

    //...
}

为什么没有对象引用注入的无限递归? 容器什么时候意识到是时候停止了?

在这种特殊情况下,您是 self-injecting 无状态 EJB。在 Wildfly 的情况下,@Stateless 与任何 CDI 作用域都没有关联,所以你的 bean 以 @Dependent 结尾(关于它是否正确的讨论可以在这里 https://issues.redhat.com/browse/CDI-414 找到)。因此,在 Wildfly 的情况下,它以错误“WELD-001443:伪作用域 bean 具有循环依赖性”结束。

当其中一个 bean(在您的情况下是同一个 bean)具有正常范围时,CDI 当前支持循环依赖(在您的情况下 self-injecting):@RequestScoped, @SessionScoped@ApplicationScoped, @ConversationScoped.

所以 @Dependent as pseudo-scope 将以 WELD-001443 结束,但其他范围可以工作,因为框架使用客户端代理(如果您记录 @Inject 变量,您可以看到 toString()将打印有关代理对象的信息)。在这个代理 CDI 框架上调用方法后进行上下文查找,这就是为什么在这个 bean 的初始化期间没有发生无限循环的原因。

对于@Dependent,没有使用代理,直接创建引用。这是 WELD-001443 的目的,以保护您免受无限循环。

除了 Petr 的出色回答之外,CDI 的核心概念之一是您实际上是在注入 Proxies,而不是实际对象。当您调用代理上的函数时,您将被路由到容器中正确的 bean 实例。这允许 self-injection 工作,以及其他场景,如将 RequestScoped bean 注入 ApplicationScoped(如果容器正在注入实际实例,这将如何工作?)