Jakarta ee 为什么CDI的自注入不会导致无限循环?

Jakarta ee 为什么CDI的自注入不会导致无限循环?,jakarta-ee,cdi,Jakarta Ee,Cdi,这项工程为什么有效 @Stateless public class SomeClass { @Inject private SomeClass self; //... } 为什么没有对象引用的无限递归? 容器何时意识到该停止了?在这种特殊情况下,您是自注入无状态EJB。在Wildfly的情况下,@Stateless与任何CDI作用域都没有关联,因此您的bean以@Dependent结尾(这里可以找到它是否正确的讨论)。因此,对于Wildfly,它以错误“WELD-0

这项工程为什么有效

@Stateless
public class SomeClass {

    @Inject
    private SomeClass self;

    //...
}
为什么没有对象引用的无限递归?
容器何时意识到该停止了?

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

当其中一个bean(在您的例子中是同一个bean)具有正常作用域时,CDI当前支持循环依赖关系(在您的例子中是自注入的):
@RequestScoped、
@SessionScoped
@ApplicationScoped
@ConversationScoped

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


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

除了Petr的伟大答案外,CDI的核心概念之一是您实际上是在注入代理,而不是实际对象。当您在代理上调用函数时,您将被路由到容器中正确的bean实例。这允许自注入工作,以及其他场景,如将RequestScope bean注入到应用程序范围(如果容器注入实际实例,这将如何工作?

我认为,因为注入是在第一次使用自变量时完成的。我认为它不需要实现任何东西;“self”实际上就是同一个EJB实例。它被创建一次,被注入一次。您可以通过在某处设置调试器断点并检查对象ID来验证它们是否相同。