CDI中的@ApplicationScoped和@Singleton范围有什么区别?

amo*_*fis 86 java scope cdi

在CDI中有@ApplicationScoped和(javax.inject)@Singleton伪范围.他们之间有什么区别?除了@ApplicationScoped代理的事实,而@Singleton不是.

我可以把我的@Singleton豆子改成@ApplicationScoped吗?可@ApplicationScoped豆有两个(或更多)的实例?

Boz*_*zho 25

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

  • 这不是真的.有一个注释javax.inject.Singleton.它是CDI的一部分.点击此处:http://docs.jboss.org/weld/reference/1.0.1-Final/en-US/html_single/#d0e1921 (10认同)
  • @amorphis - 我面前有CDI规范.我甚至已经实现了它的一部分,并没有提到有关`@ Singleton`的任何内容.仅在一个示例中示出,没有说明.确实,CDI依赖于`javax.inject`,但严格来说它不是CDI规范的一部分.那就是说,我纠正了我的回答. (4认同)

And*_*ich 16

简而言之:你甚至可以混合(@Singleton@ApplicationScoped)它在某些情况下是有意义的. (并在我的预期工作!)

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

对我来说,这个问题是由如何强制应用程序范围的bean在应用程序启动时实例化而开发的? 在一些讨论中我说了这个,到目前为止找不到有效的论据:

在很多现实生活场景/设置中,我会说从概念/建模的角度来看,很难肯定地说 - 某些东西是(或将会变成/被视为)EJB或应用程序范围的托管bean.

到目前为止(从我的观点来看)(有争议的但不是决定性的)论点(@BalusC和所有其他人:我希望看到它们具有决定性,但如果没有,上述情况可能适用,但论证可能仍然存在.仍然帮助读者获得差异/优点/缺点/坏/良好做法)

EJB与Managed Bean

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

但:

:我认为你不太正确并且夸大了意义/用法,这看起来对我很有争议.http://en.wikipedia.org/wiki/Enterprise_JavaBeans

Enterprise JavaBeans(EJB)是一种用于企业软件模块化构建的托管服务器软件,也是多种Java API之一.EJB是一个服务器端软件组件,它封装了应用程序的业务逻辑.

企业豆类型

会话豆[3]可以是"有状态","无国籍"或"单身"[...]

消息驱动的豆[...]

...在我的案例中仍然适用.

Singleton EJB与Application Scoped Bean

锁定

BalusC:单例EJB与应用程序作用域bean不同.单例EJB是读/写锁定的,因此对于您考虑的任务可能效率低/过度卷积.简而言之:获取一本优秀的Java EE书籍并学习如何使用正确的工具.一种方式绝对不是另一种方式.它的工作原理并不意味着它是正确的工具.大锤能够拧紧螺丝,但它不一定是正确的工具:)

但:

(我不能看到大锤这里-对不起......)这是很好的了解锁定默认值(我不知道它),但这似乎又是不正确的:甲骨文Java EE 6教程管理的并行访问单例会话Bean

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

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


cov*_*ner 9

@Singleton在JSR-299中引用的是Singleton会话bean(javax.ejb.Singleton而不是javax.inject.Singleton),而不是名为Singleton的内置作用域中的JSR-299托管bean.

您可能会在服务器中找到@ApplicationScoped每个EAR一个或每个WAR/EJB-JAR一个,因为它在规范中并不清楚,但您绝对不应期望它是每个JVM一个.


G. *_*cki 8

通常当你想只有一个对象的一个​​实例时,你可能应该使用@ApplicationScoped注释 - 这样的对象被代理,因此甚至可以开箱即用地正确序列化.

另一方面,也有很多情况,你只需要一个类的实例,但这样的类不能代理(例如因为是最终的) - 然后@Singleton是一个救援.因为Singleton它是伪范围,并且不像任何"正常"范围那样被代理.

  • 也就是说,我确实知道 EJB 是被代理的。我的困惑部分在于你对单身人士所做的区分。 (3认同)

vig*_*gor 6

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

使用CDI 1.1规范:在发现模式=带注释的应用程序中,Weld无法识别Bean,@Singleton也不会加载该bean