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

问题描述 投票:85回答:6

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

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

java scope cdi
6个回答
25
投票

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


16
投票

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

除了到目前为止的其他答案,我想在现实世界的场景中添加更多要点,以供澄清。

对我来说,这个问题来自How do I force an application-scoped bean to instantiate at application startup?在一些讨论中,我曾说过这一点,但到目前为止,找不到针对它的有效论点:

[在许多实际场景/设置中,我会说很难可以肯定地说-从抽象/建模的角度来看-是(或将被/将被视为)EJB或应用程序范围的托管bean。

到目前为止,[[(从我的观点来看,有争议但不是结论性的)论点:(@BalusC和所有其他人:我希望看到它们具有决定性,但如果不是,以上内容可能成立,尽管如此,论点仍可能有助于读者理解不同点/优势/劣势/不良/良好做法)) >

EJB与托管Bean

BalusC

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

me

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

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

Enterprise Bean的类型

Session Bean [3]可以是“有状态”,“无状态”或“单人” [...]

消息驱动的Bean [...]

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

Singleton EJB与应用程序范围的Bean

锁定

BalusC

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

((我在这里看不到大锤,对不起...)很高兴知道锁定默认值(我没有意识到),但这似乎又是不正确的:Oracle Java EE 6 Tutorial on Managing Concurrent Access in a Singleton Session Bean

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

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

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

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

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

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

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

使用CDI 1.1规范:在发现模式下的应用程序=带注释时,Weld不会使用@Singleton标识bean并且未加载此bean

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

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

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

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


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

使用CDI 1.1规范:在发现模式下的应用程序=带注释时,Weld不会使用@Singleton标识bean并且未加载此bean


2
投票
[可以使用默认构造函数编写类的主要区别之一是在使用javax.inject.Singleton时具有私有访问修饰符,但是在使用javax.enterprise.context.ApplicationScoped时您的类应该具有至少具有默认访问修饰符的默认构造函数,并且这是JBOSS 6.1 GA Final实施
© www.soinside.com 2019 - 2024. All rights reserved.