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

时间:2021-11-24 13:37:07

In CDI there is the @ApplicationScoped and the (javax.inject) @Singleton pseudo-scope. What is the difference between them? Besides the fact that @ApplicationScoped is proxied, and @Singleton is not.

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

Can I just change my @Singleton bean to @ApplicationScoped? Can @ApplicationScoped bean have two (or more) instances?

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

6 个解决方案

#1


19  

@Singleton is not part of the CDI specification. It is part of EJB and javax.inject (JSR-330). It is not mentioned in the spec what is its behaviour, so you can only rely on what's written in the Weld documentation.

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

#2


9  

in short: You can even mix it (@Singleton and @ApplicationScoped) and it makes sense in some scenarios. (and works as expected in mine!)

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

Additionally to the other answers so far I'd like to add some more points for clarification in real world scenarios.

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

For me this question developed out of How do I force an application-scoped bean to instantiate at application startup? In some discussion there I stated this and can't find a valid argument against it so far:

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

In a lot of real-life scenarios/setups I would say it's hard to definitely say - from an abstract/modelling point of view - whether something is (or will become/be treated like) an EJB or an application-scoped managed bean.

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

(debatable but not conclusive) arguments (from my point of view) against it so far: (@BalusC and all others: I'd like to see them beeing conclusive, but if not, the above may hold true and nevertheless the arguments may still help the reader to get the differences/advantages/disadvantages/ bad/good practices)

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

EJB vs. Managed Bean

BalusC: That's an EJB not a managed bean, which is quite different. EJBs run in backend and managed beans in frontend. EJBs run in transactional context too. [...] You just confused enterprise beans with managed beans and I just pointed out that.

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

but:

但:

me: I think you are not quite correct and overstating the meaning/usage and it looks debatable to me. http://en.wikipedia.org/wiki/Enterprise_JavaBeans

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

Enterprise JavaBeans (EJB) is a managed, server software for modular construction of enterprise software, and one of several Java APIs. EJB is a server-side software component that encapsulates the business logic of an application.

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

Types of Enterprise Beans

企业豆类型

Session Beans [3] that can be either "Stateful", "Stateless" or "Singleton" [...]

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

Message Driven Beans [...]

消息驱动豆[...]

... which still holds true in my case.

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

Singleton EJB vs. Application Scoped Bean

Locking

BalusC: A singleton EJB isn't the same as an application scoped bean. A singleton EJB is read/write locked and thus potentially inefficient/overconvoluted for the task you had in mind. Long story short: Grab a good Java EE book and learn to use the right tool for the job. One way definitely isn't the other way. That it works doesn't mean that it's the right tool. A sledgehammer is capable of fastening a screw, but it isn't necessarily the right tool to that :)

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

but:

但:

(I can't see the sledgehammer here - sorry ...) It's good to know the locking defaults (I was not aware of it), but this seems to be incorrect again: Oracle Java EE 6 Tutorial on Managing Concurrent Access in a Singleton Session Bean

(我在这里看不到大锤 - 抱歉......)知道锁定默认值(我不知道)很好,但这似乎又不正确了:Oracle Java EE 6管理并发访问的教程单例会话Bean

When creating a singleton session bean, concurrent access to the singleton’s business methods can be controlled in two ways: container-managed concurrency and bean-managed concurrency. [...]

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

Although by default, singletons use container-managed concurrency, the @ConcurrencyManagement(CONTAINER) annotation may be added at the class level of the singleton to explicitly set the concurrency management type

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

#3


8  

@Singleton in JSR-299 refers to Singleton session beans (javax.ejb.Singleton, not javax.inject.Singleton), not JSR-299 managed beans in a built-in scope called Singleton.

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

You might find in your server that @ApplicationScoped is one-per EAR or one-per WAR/EJB-JAR as it is not clear in the specification, but you should definitely not expect it to be one per JVM.

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

#4


4  

Usually when you want to have only one instance of some object you probably should use @ApplicationScoped annotation - such object is proxied and thus can even be properly serialized out-of-the-box.

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

On the other hand, there are also many cases, where you want only one instance of the class, but such class cannot be proxied (e.g. because of being final) - then @Singleton is a rescue. Because Singleton is a pseudo-scope and is not being proxied like any "normal" scope.

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

#5


4  

There is one more difference: @Singleton is not bean defining annotations, as the Singleton scope is not a normal scope. Then @ApplicationScoped is bean defining annotations.

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

With CDI 1.1 spec: When application in discovery-mode = annotated, Weld does not identify beans with @Singleton and not loaded this

使用CDI 1.1规范:当发现模式中的应用程序=注释时,Weld不识别带有@Singleton的bean而不加载此

#6


2  

One of the major differences that you can write your class with default contractor has private access modifier when using javax.inject.Singleton, but your class should have default contractor with at least default access modifier when using javax.enterprise.context.ApplicationScoped and this is JBOSS 6.1 GA Final implementation

使用javax.inject.Singleton时,您可以使用默认承包商编写类的主要区别之一是私有访问修饰符,但是当使用javax.enterprise.context.ApplicationScoped时,您的类应该具有至少具有默认访问修饰符的默认承包商是JBOSS 6.1 GA最终实现

#1


19  

@Singleton is not part of the CDI specification. It is part of EJB and javax.inject (JSR-330). It is not mentioned in the spec what is its behaviour, so you can only rely on what's written in the Weld documentation.

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

#2


9  

in short: You can even mix it (@Singleton and @ApplicationScoped) and it makes sense in some scenarios. (and works as expected in mine!)

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

Additionally to the other answers so far I'd like to add some more points for clarification in real world scenarios.

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

For me this question developed out of How do I force an application-scoped bean to instantiate at application startup? In some discussion there I stated this and can't find a valid argument against it so far:

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

In a lot of real-life scenarios/setups I would say it's hard to definitely say - from an abstract/modelling point of view - whether something is (or will become/be treated like) an EJB or an application-scoped managed bean.

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

(debatable but not conclusive) arguments (from my point of view) against it so far: (@BalusC and all others: I'd like to see them beeing conclusive, but if not, the above may hold true and nevertheless the arguments may still help the reader to get the differences/advantages/disadvantages/ bad/good practices)

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

EJB vs. Managed Bean

BalusC: That's an EJB not a managed bean, which is quite different. EJBs run in backend and managed beans in frontend. EJBs run in transactional context too. [...] You just confused enterprise beans with managed beans and I just pointed out that.

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

but:

但:

me: I think you are not quite correct and overstating the meaning/usage and it looks debatable to me. http://en.wikipedia.org/wiki/Enterprise_JavaBeans

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

Enterprise JavaBeans (EJB) is a managed, server software for modular construction of enterprise software, and one of several Java APIs. EJB is a server-side software component that encapsulates the business logic of an application.

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

Types of Enterprise Beans

企业豆类型

Session Beans [3] that can be either "Stateful", "Stateless" or "Singleton" [...]

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

Message Driven Beans [...]

消息驱动豆[...]

... which still holds true in my case.

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

Singleton EJB vs. Application Scoped Bean

Locking

BalusC: A singleton EJB isn't the same as an application scoped bean. A singleton EJB is read/write locked and thus potentially inefficient/overconvoluted for the task you had in mind. Long story short: Grab a good Java EE book and learn to use the right tool for the job. One way definitely isn't the other way. That it works doesn't mean that it's the right tool. A sledgehammer is capable of fastening a screw, but it isn't necessarily the right tool to that :)

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

but:

但:

(I can't see the sledgehammer here - sorry ...) It's good to know the locking defaults (I was not aware of it), but this seems to be incorrect again: Oracle Java EE 6 Tutorial on Managing Concurrent Access in a Singleton Session Bean

(我在这里看不到大锤 - 抱歉......)知道锁定默认值(我不知道)很好,但这似乎又不正确了:Oracle Java EE 6管理并发访问的教程单例会话Bean

When creating a singleton session bean, concurrent access to the singleton’s business methods can be controlled in two ways: container-managed concurrency and bean-managed concurrency. [...]

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

Although by default, singletons use container-managed concurrency, the @ConcurrencyManagement(CONTAINER) annotation may be added at the class level of the singleton to explicitly set the concurrency management type

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

#3


8  

@Singleton in JSR-299 refers to Singleton session beans (javax.ejb.Singleton, not javax.inject.Singleton), not JSR-299 managed beans in a built-in scope called Singleton.

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

You might find in your server that @ApplicationScoped is one-per EAR or one-per WAR/EJB-JAR as it is not clear in the specification, but you should definitely not expect it to be one per JVM.

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

#4


4  

Usually when you want to have only one instance of some object you probably should use @ApplicationScoped annotation - such object is proxied and thus can even be properly serialized out-of-the-box.

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

On the other hand, there are also many cases, where you want only one instance of the class, but such class cannot be proxied (e.g. because of being final) - then @Singleton is a rescue. Because Singleton is a pseudo-scope and is not being proxied like any "normal" scope.

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

#5


4  

There is one more difference: @Singleton is not bean defining annotations, as the Singleton scope is not a normal scope. Then @ApplicationScoped is bean defining annotations.

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

With CDI 1.1 spec: When application in discovery-mode = annotated, Weld does not identify beans with @Singleton and not loaded this

使用CDI 1.1规范:当发现模式中的应用程序=注释时,Weld不识别带有@Singleton的bean而不加载此

#6


2  

One of the major differences that you can write your class with default contractor has private access modifier when using javax.inject.Singleton, but your class should have default contractor with at least default access modifier when using javax.enterprise.context.ApplicationScoped and this is JBOSS 6.1 GA Final implementation

使用javax.inject.Singleton时,您可以使用默认承包商编写类的主要区别之一是私有访问修饰符,但是当使用javax.enterprise.context.ApplicationScoped时,您的类应该具有至少具有默认访问修饰符的默认承包商是JBOSS 6.1 GA最终实现