将较短范围的 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 实例 - 它是如何工作的?的主要内容,如果未能解决你的问题,请参考以下文章

CDI 动态 Bean 实例

是否有可能在运行时检测CDI托管bean的范围?

如何以编程方式将 Java CDI 托管 bean 注入(静态)方法中的局部变量

cdi bean 中的资源注入

使用 CDI/Weld 注入通用 Bean

使用 CDI(上下文和依赖注入)支持 bean 而不是托管 Bean