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


92

在CDI中有@ApplicationScoped和(javax.inject@Singleton伪作用域。它们之间有什么区别?除了@ApplicationScoped被代理和@Singleton不被代理的事实。

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


11
您阅读过Weld参考资料吗?在第5.4节(第36页)中有关于@ApplicationScoped和之间的实际差异的一些解释@Singleton
brandizzi 2011年

3
我还发现本文结尾处的差异摘要germanescobar.net/2010/04/…有用
matt freake 2015年

1
您要指的是哪个Singleton范围-javax.ejb或javax.inject?
John Ament

Answers:


29

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


11
这不是真的。有注释javax.inject.Singleton。它是CDI的一部分。查看此处:docs.jboss.org/weld/reference/1.0.1-Final/en-US/html_single/...
amorfis

5
@amorphis-我面前有CDI规范。我什至已经实现了其中的一部分,并且没有提及任何内容@Singleton。仅在一个示例中显示,没有任何说明。CDI确实依赖于javax.inject,但严格来说,它不是CDI规范的一部分。就是说,我稍微纠正了我的答案。
博佐2010年

17

简而言之:您甚至可以将其(@Singleton@ApplicationScoped)混合使用,并且在某些情况下很有意义。 (并且按我的预期工作!)

除了到目前为止的其他答案外,我想补充一些要点,以便在现实世界中进行说明。

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

在很多实际场景/设置中,从抽象/建模的角度来看,很难说肯定是-某事物是(或将被视为)EJB或应用程序范围内的受管bean。

到目前为止(从我的角度来看)的争论(有争议但不是决定性的):(@ BalusC和所有其他人:我希望看到他们具有决定性,但如果不是,则以上说法可能成立,尽管如此,论点仍可能成立仍然可以帮助读者了解差异/优势/劣势/不良/良好做法)

EJB与托管Bean

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

但:

:我认为您不太正确并且夸大了其含义/用法,这对我来说值得商bat。http://en.wikipedia.org/wiki/Enterprise_JavaBeans

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

企业Bean的类型

可以为“有状态”,“无状态”或“单人”的会话Bean [3] [...]

消息驱动的豆[...]

...在我看来仍然如此。

Singleton EJB与应用程序范围的Bean

锁定

BalusC:单例EJB与应用程序范围的bean不同。单例EJB被读/写锁定,因此对于您所考虑的任务可能效率低下/卷积过多。长话短说:拿一本好的Java EE书,学习使用正确的工具来完成这项工作。一种方法肯定不是另一种方法。它起作用并不意味着它是正确的工具。大锤可以固定螺丝,但不一定是正确的工具:)

但:

(我在这里看不到大锤,对不起...)很高兴知道锁定默认值(我没有意识到),但这似乎又是不正确的:Oracle Java EE 6教程中的管理并发访问”。单例会话Bean

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

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


混合不会使Weld感到有趣:加载应用程序时发生异常:CDI定义失败:WELD-000046:最多可以在[EnhancedAnnotatedTypeImpl]公共ApplicationScoped Singleton MyClass上指定一个范围。使用javax.inject.Singleton。
sgflt

10

通常,当您只希望某个对象的一个​​实例时,您可能应该使用@ApplicationScoped批注-该对象被代理,因此甚至可以即开即用地正确序列化。

另一方面,在很多情况下,您只需要该类的一个实例,但是无法代理该类(例如,因为是最终的),这@Singleton是一种拯救。因为Singleton是伪作用域,并且不像任何“正常”范围那样被代理。


我对此表示不满,因为目前还不清楚。我从事Java EE编程已经有五年了,参加了教程和阅读了本书,但是我不清楚你说“代理此类对象”,“甚至可以正确序列化”和“伪代码”时的意思。范围”。我很想知道这是什么意思,因为听起来您知道您在说什么,但是正如撰写本文时,我无法想象您的回答将对大多数Java EE开发人员有所帮助。
DavidS

2
就是说,我确实知道EJB被代理了。我的困惑部分是围绕您对Singletons所做的区分。
DavidS

9

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

您可能会在服务器中发现@ApplicationScoped每个EAR一个或每个WAR / EJB-JAR一个,因为规范中没有明确规定,但是您绝对不应期望每个JVM一个。


7

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

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


2

您可以使用默认构造函数编写类的主要区别之一是使用时具有私有访问修饰符javax.inject.Singleton,但是使用时您的类应具有至少具有默认访问修饰符的默认构造函数javax.enterprise.context.ApplicationScoped,这就是JBOSS 6.1 GA Final实现


您是说“默认构造函数”吗?
树鱼张
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.