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

在CDI中有@ApplicationScoped和( javax.inject@Singleton伪范围。 他们有什么区别? 除了@ApplicationScoped被代理,而@Singleton不是。

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

@Singleton不是CDI规范的一部分。 它是EJB和javax.inject (JSR-330)的一部分。 在规范中没有提到它的行为,所以你只能依靠Weld文档中写的东西。

简而言之:你甚至可以将它混合( @Singleton@ApplicationScoped ),在某些情况下它是有意义的。 (和我的预期一样!)

除了到目前为止的其他答案,我想补充一些在现实世界的情况下澄清点。

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

在很多现实生活场景/设置中,我会说, 从抽象/build模的angular度来看,很难确定是否有(或将会被视为)EJB或应用程序范围的pipe理bean。

(从我的观点来看)迄今为止反对的论点(@BalusC和所有其他人:我希望看到他们的结论是肯定的,但是如果不是这样,上述观点可能是真实的,仍然帮助读者得到差异/优点/缺点/差/良好做法)

EJB与托pipeBean

BalusC :这是一个EJB而不是一个托pipe的bean,这是一个非常不同的东西。 EJB在后端运行,在前端运行被pipe理的bean。 EJB也在事务上下文中运行。 […]您只是将企业bean与托pipebean混淆了,我只是指出了这一点。

但:

:我认为你不太正确,夸大其意义/用法,这对我来说似乎有争议。 http://en.wikipedia.org/wiki/Enterprise_JavaBeans

企业JavaBeans(EJB)是一种用于企业软件模块化构build的托pipe服务器软件,也是几种Java API之一。 EJB是封装应用程序业务逻辑的服务器端软件组件。

企业豆类

会话Bean [3]可以是“有状态”,“无状态”或“单例”

消息驱动豆[…]

…在我的情况下仍然如此。

单身EJB与应用程序范围的Bean

locking

BalusC :单例EJB与应用程序范围的bean不一样。 单例EJB是读/写locking的,因此可能效率低下/过度卷积,因为您头脑中想的任务。 长话短说:抓住一本好的Java EE书,并学习使用正确的工具。 一种方法绝对不是另一种方式。 它的作品并不意味着它是正确的工具。 大锤可以固定螺丝,但它不一定是正确的工具:)

但:

(我在这里看不到大锤 – 对不起…)知道locking的默认值(我没有意识到这一点)是很好的,但是这似乎又不正确: Oracle Java EE 6 pipe理并发访问 教程 单身会话Bean

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

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

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

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

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

使用CDI 1.1规范:当应用程序在发现模式=注释,Weld不识别@Singleton豆,并没有加载此

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

另一方面,也有很多情况下,你只需要一个类的实例,但这样的类不能被代理(例如,因为是最终的) – 那么@Singleton是一个救援。 因为Singleton是一个伪范围,并不像任何“正常”范围代理。

在使用javax.inject.Singleton时,您可以使用默认承包商编写您的类的主要差异之一是具有私人访问修饰符,但是在使用javax.enterprise.context.ApplicationScoped时,您的类应该具有至less具有默认访问修饰符的默认承包商。是JBOSS 6.1 GA Final实现