Java CDI中@ApplicationScoped和@Singleton作用域之间有什么区别?

Java CDI中@ApplicationScoped和@Singleton作用域之间有什么区别?,java,scope,cdi,Java,Scope,Cdi,在CDI中有@ApplicationScoped和(javax.inject)@Singleton伪作用域。他们之间有什么区别?除此之外,@ApplicationScoped是代理的,而@Singleton不是代理的 我可以将我的@Singletonbean更改为@ApplicationScoped?@ApplicationScopedbean是否可以有两个(或更多)实例?@Singleton不是CDI规范的一部分。它是EJB和javax.inject(JSR-330)的一部分。规范中没有提到它

在CDI中有
@ApplicationScoped
和(
javax.inject
@Singleton
伪作用域。他们之间有什么区别?除此之外,
@ApplicationScoped
是代理的,而
@Singleton
不是代理的


我可以将我的
@Singleton
bean更改为
@ApplicationScoped
@ApplicationScoped
bean是否可以有两个(或更多)实例?

@Singleton
不是CDI规范的一部分。它是EJB和javax.inject(JSR-330)的一部分。规范中没有提到它的行为,因此您只能依赖于Weld文档中编写的内容。

@Singleton
在JSR-299中指的是单例会话bean(
javax.ejb.Singleton
,而不是
javax.inject.Singleton
),而不是名为Singleton的内置范围中的JSR-299托管bean


您可能会在服务器中发现,
@ApplicationScoped
是每个EAR一个或每个WAR/EJB-JAR一个,因为规范中不清楚,但是您绝对不应该期望每个JVM有一个。当使用
javax.inject.Singleton时,您可以使用默认构造函数编写类的主要区别之一是具有私有访问修饰符,但是当使用
javax.enterprise.context.ApplicationScoped
时,您的类应该具有至少带有默认访问修饰符的默认构造函数,这是
JBOSS 6.1 GA Final
实现

通常当您只想拥有某个对象的一个实例时,您可能应该使用
@ApplicationScoped
注释-这样的对象是代理的,因此甚至可以在开箱即用的情况下正确序列化


另一方面,在许多情况下,您只需要类的一个实例,但无法代理此类(例如,因为它是final)-那么
@Singleton
就是一种拯救。因为
Singleton
是一个伪作用域,不像任何“正常”作用域那样被代理。

简言之:您甚至可以将其混合使用(
@Singleton
@ApplicationScoped
),在某些情况下它是有意义的。
(并且在我的矿井中工作如期!)

除了到目前为止的其他答案之外,我还想在现实世界场景中补充一些澄清的要点

对我来说,这个问题是由 在一些讨论中,我指出了这一点,但到目前为止,我找不到有效的论据来反对它:

在许多现实生活场景/设置中,我会说这很难做到 明确地说——从抽象/建模的角度来看——是否 某些东西是(或将成为/被视为)EJB或应用程序范围的托管bean。

(有争议但不是结论性的)到目前为止反对它的论据(从我的观点): (@BalusC和所有其他人:我希望看到他们是结论性的,但如果不是,上述观点可能是正确的,尽管如此,这些论点仍然可以帮助读者了解差异/优点/缺点/坏/好的做法)

EJB与托管Bean BalusC:这是一个EJB而不是托管bean,这是完全不同的。EJB在后端运行,托管bean在前端运行。EJB也在事务上下文中运行。 […]您刚刚混淆了企业bean和托管bean,我刚才指出了这一点

但是:

我:我认为你不太正确,夸大了它的含义/用法,在我看来这是有争议的

EnterpriseJavaBeans(EJB)是一种用于企业软件模块化构建的托管服务器软件,是几种JavaAPI之一。EJB是一个服务器端软件组件,它封装了应用程序的业务逻辑

企业bean的类型

会话bean[3]可以是“有状态”、“无状态”或“单例”[…]

消息驱动bean[…]

。。。我的情况仍然如此

单例EJB与应用范围Bean 锁定 BalusC:单例EJB与应用程序范围的bean不同。单例EJB是读/写锁定的,因此对于您想到的任务来说可能效率低下/过度转换。长话短说:抓起一本好的JavaEE书籍,学习使用合适的工具来完成工作。一种方式肯定不是另一种方式。它有效并不意味着它是正确的工具。大锤可以紧固螺钉,但不一定是正确的工具:)

但是:

(我在这里看不到大锤-对不起…) 知道锁定默认值很好(我没有意识到),但这似乎还是不正确的:

创建单例会话bean时,可以通过两种方式控制对单例业务方法的并发访问:容器管理的并发和bean管理的并发。 [……]

尽管默认情况下,单例使用容器管理的并发,但可以在单例的类级别添加@ConcurrencyManagement(容器)注释,以显式设置并发管理类型


还有一个区别:
@Singleton
不是bean定义的注释,因为
Singleton
范围不是正常范围。 然后,
@ApplicationScoped
是bean定义的注释


使用CDI 1.1规范:当发现模式下的应用程序=注释时,Weld不会使用
@Singleton
识别bean,也不会加载此我知道这是一篇旧文章,但我经常被问到这个问题

IMHO,转到源->

提供了一个很好的参考,在实际使用方面比较了两者


(这也有助于注意,在最后一种情况下,Quarkus为您创建无args构造函数以满足CDI bean的要求,因此您不需要DIY或Lombok。)

这不是真的。还有注释javax.inject.Singleton。它是CDI的一部分。检查这里:@amorphis-我在f中有CDI规范