为啥无状态 bean 被视为伪作用域并且不能具有循环依赖关系?
Posted
技术标签:
【中文标题】为啥无状态 bean 被视为伪作用域并且不能具有循环依赖关系?【英文标题】:Why stateless beans are treated as pseudo-scoped and cannot have circular dependencies?为什么无状态 bean 被视为伪作用域并且不能具有循环依赖关系? 【发布时间】:2014-12-15 13:13:29 【问题描述】:使用 Wildfly 8.1 我有几个 bean,我尝试将几个 EJB 相互注入。假设我有 3 个豆子:
@Stateless
public class A
@Inject
private B b;
@Stateless
public class B
@Inject
private C c;
@Stateless
public class C
@Inject
private A a;
显然,我有循环依赖。根据规范:
容器需要支持 bean 中的循环 至少有一个 bean 参与其中的依赖关系图 循环依赖链具有正常范围
在容器中运行上述代码会导致以下形式的错误:
org.jboss.weld.exceptions.DeploymentException: WELD-001443: Pseudo scoped bean 有循环依赖。依赖路径:
-会话 bean [class A with 限定符 [@Default @Any];本地接口是 [一种] BackedAnnotatedField] @Inject private B,
[..]
我的问题是:@Stateless bean 的范围是什么?默认情况下是@Dependent吗?最重要的是如何启用无状态会话 bean 之间的循环依赖关系?
对不起,如果问题太琐碎。我将感谢任何可以解释所呈现行为的好的进一步阅读资源。提前致谢。
更新 好的。我找到了解决方法。我使用了@EJB 注释而不是@Inject,但这并不能解释@Inject 的奇怪行为。这个问题仍然悬而未决,但正如 Mika 所说,这可能是 CDI 规范和 Weld RI 中未解决的问题。
【问题讨论】:
我没有答案,但这不是一个小问题。 CDI EG 成员之间就此进行了讨论。看看 CDI spec jira,应该有关于这个话题的问题。 @MikeBraun 您能否提供指向 jira 问题的链接?我已经搜索过了,但我不确定我找对了。 它是 CDI-414,见 issues.jboss.org/browse/CDI-414 谢谢。正如它在描述中所写的那样,当前的解决方法与我在更新中所写的相同。所以现在我会把它作为一个答案。 CDI-414 处理自注入,而不是循环注入。 【参考方案1】:这是 wildfly/jboss CDI 实现中的一个错误。问题描述https://issues.jboss.org/browse/CDI-414 中提供的当前解决方法(由@MikeBraun 建议)是使用@EJB 注释而不是@Inject。
【讨论】:
【参考方案2】:@Stateless
没有作用域,并且与任何作用域都没有关联。您的 bean 以 @Dependent
结尾,因为您没有在 bean 上注释任何其他范围。
你需要给他们一个正常的范围 - @RequestScoped
或 @ApplicationScoped
,但我不确定它们是否适合你的情况。
【讨论】:
您的解决方案只有在 Web 层内进行管理时才有效。因为它是 EJB bean,所以它是 CDI 实现中的一个错误。 我不同意这一点。确定无状态范围在这里毫无意义,我认为它甚至行不通。只有有状态的 bean 可以有范围。事实上,对于“@Stateless”这一现象,CDI 并没有真正令人信服的答案。无状态 bean 更像是一个监听消息的端点,而不是一个普通的 bean。这就是为什么自注入和循环依赖都不是问题的原因。无状态代理更像是一个 URL。当一个方法调用发生时,它被发送到该类型的任何 bean(一个新实例,一个来自池的实例,总是相同的,......)。所以这里的请求范围是完全错误的。【参考方案3】:这并不能回答整个问题,但是当我搜索循环依赖异常时,它是谷歌上的第一次点击。希望这将帮助其他程序员在这里找到更快的答案是我的解决方案。
导致循环依赖异常的代码:
class A
@Inject B b;
public void foo()
b.bar();
public void quux()
//some code
class B
@Inject A a;
public void bar()
//some code
public void baz()
a.quux();
解决问题的方法是使用javax.enterprise.inject.Instance
class A
@Inject B b;
public void foo()
b.bar();
public void quux()
//some code
class B
@Inject Instance<A> a;
public void bar()
//some code
public void baz()
a.get().quux();
【讨论】:
以上是关于为啥无状态 bean 被视为伪作用域并且不能具有循环依赖关系?的主要内容,如果未能解决你的问题,请参考以下文章