将较短范围的 Bean 实例注入 CDI 中较大范围的 bean 实例 - 它是如何工作的?
Posted
技术标签:
【中文标题】将较短范围的 Bean 实例注入 CDI 中较大范围的 bean 实例 - 它是如何工作的?【英文标题】:Bean instance of a shorter scope injected in a bean instance of a larger scope in CDI - how does it work? 【发布时间】:2011-09-28 10:56:23 【问题描述】:考虑以下请求范围的 CDI bean:
@RequestScoped
public class RequestScopedBean
// ...
现在,我将它注入到应用程序范围的 bean 中:
@ApplicationScoped
public class ApplicationScopedBean
@Inject private RequestScopedBean requestScopedBean;
// ...
我运行此代码并注意到两个请求之间的请求范围的 bean 实例不同,但应用程序范围的 bean 实例是相同的。我的疑问是:这是如何工作的?请求范围的 bean 实例是否在每个请求中重新归属于应用范围的字段?还是应用范围 bean 的代理只是在请求之间发生变化?
【问题讨论】:
@jangroth 4.9 Client Proxies 章节提供了一个概述,但没有解释它是如何工作的。具体来说,当单个@ApplicationScoped
bean 注入了@SessionScoped
bean 并从@RequestScoped
方法接收两个并行调用时会发生什么?
您确实注意到这个问题是 4 年前提出的,而 CDI / Weld(及其文档)在此期间出现了一些版本问题? ;)
【参考方案1】:
在 CDI 中,每个注入的对象实际上都是一个代理。因此,在这种情况下,代理可能持有对 RequestContext
的引用,并且在每次方法调用时都会获取正确的 bean 实例。
【讨论】:
在核心上是正确的,但在细节上不是。DependentScoped
bean 和 SingletonScoped
bean 永远不会被代理。这两个作用域都是所谓的伪作用域。
应用范围是伪范围吗?我不确定。无论如何,我的观点是关于特定示例 - 请求上下文。
不,不是 ApplicationScope,而是 SingletonScope。这就是为什么使用 ApplicationScope 总是更好的原因:-)
只是为了让别人明白这一点,CDI 中没有 SingletonScoped 这样的东西,有一个不受欢迎的继子 @javax.inject.Singleton 继承自“JSR-330 Dependency Injection for爪哇”。应该不惜一切代价避免它,ApplicationScoped 很可能会以任何方式满足您的需求。以上是关于将较短范围的 Bean 实例注入 CDI 中较大范围的 bean 实例 - 它是如何工作的?的主要内容,如果未能解决你的问题,请参考以下文章