为什么使用 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(如果容器正在注入实际实例,这将如何工作?)
为什么这个建筑有效?
@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(如果容器正在注入实际实例,这将如何工作?)