Java 无状态会话 Bean 与单例会话 Bean

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2013978/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 02:33:20  来源:igfitidea点击:

Stateless Session Beans vs. Singleton Session Beans

javasingletonejb-3.0ejbstateless

提问by deamon

The Java EE 6 Tutorialsays:

Java EE 6教程说:

To improve performance, you might choose a stateless session bean if it has any of these traits:

  • The bean's state has no data for a specific client.
  • In a single method invocation, the bean performs a generic task for all clients. For example, you might use a stateless session bean to send an email that confirms an online order.
  • The bean implements a web service.

Singleton session beans are appropriate in the following circumstances:

  • State needs to be shared across the application.
  • A single enterprise bean needs to be accessed by multiple threads concurrently.
  • The application needs an enterprise bean to perform tasks upon application startup and shutdown.
  • The bean implements a web service.

为了提高性能,您可以选择具有以下任何特征的无状态会话 bean:

  • bean 的状态没有特定客户端的数据。
  • 在单个方法调用中,bean 为所有客户端执行通用任务。例如,您可以使用无状态会话 bean 发送确认在线订单的电子邮件。
  • bean 实现了一个 Web 服务。

单例会话 bean 适用于以下情况:

  • 状态需要在整个应用程序中共享。
  • 单个企业 bean 需要被多个线程同时访问。
  • 应用程序需要一个企业 bean 来在应用程序启动和关闭时执行任务。
  • bean 实现了一个 Web 服务。

But what to use if:

但是在以下情况下使用什么:

  • no state has to be shared across the application
  • a single enterprise bean could be accessed by multiple threads concurrently
  • no tasks on startup or shotdown need to be performed
  • 无需在整个应用程序中共享状态
  • 多个线程可以同时访问单个企业 bean
  • 无需执行启动或击落任务

Say for example I have a login service with the following interface:

举例来说,我有一个具有以下界面的登录服务:

public interface LoginService {
  boolean authenticate(String user, String password);
}

Should it be annotated with @Singleton or @Stateless? What are the benefits of the one and the other? What if LoginService needs to get injected an EntityManager (which would be used concurrently)?

应该用@Singleton 还是@Stateless 进行注释?一个和另一个的好处是什么?如果 LoginService 需要注入一个 EntityManager(将同时使用)怎么办?

Addition:I'm thinking about the Java EE counterpart of Spring service beans, which are stateless singletons. If I understand that correctly the Java EE counterpart are @Stateless session beans and @Singleton Beans are used to configure the application at startup or cleanup at shutdown or to hold application wide objects. Is this correct?

另外:我在考虑 Spring 服务 bean 的 Java EE 对应物,它们是无状态单例。如果我正确理解 Java EE 对应物是 @Stateless 会话 bean,@Singleton Beans 用于在启动时配置应用程序或在关闭时清理或保存应用程序范围的对象。这样对吗?

回答by mjn

I would go for Stateless - the server can generate many instances of the bean and process incoming requests in parallel.

我会选择无状态 - 服务器可以生成许多 bean 实例并并行处理传入请求。

Singleton sounds like a potential bottleneck - the default @Lock value is @Lock(WRITE) but may be changed to @Lock(READ) for the bean or individual methods.

Singleton 听起来像是一个潜在的瓶颈——默认的 @Lock 值是 @Lock(WRITE) 但对于 bean 或单个方法可能会更改为 @Lock(READ)。

回答by cn1h

I think Singleton in concurrency usage will not perform worse than SLSB Pool, it might be even better. The only problem is if you want to share something between threads, you need lock it, and that could be a big problem of performance. So in that case, a SLSB Pool perform much better, because it's not 100% singleton, there are more instances, one got locked, the other one comes up. Anyway if the lock is on some resource sharing by all SLSBs, the pool won't help neither.

我认为并发使用中的 Singleton 不会比 SLSB Pool 表现更差,它可能会更好。唯一的问题是如果你想在线程之间共享某些东西,你需要锁定它,这可能是一个很大的性能问题。所以在那种情况下,SLSB 池的性能要好得多,因为它不是 100% 单例,有更多的实例,一个被锁定,另一个出现。无论如何,如果锁定在所有 SLSB 共享的某些资源上,则池也无济于事。

In short, I think singleton is better than SLSB Pool, you should use it if you can. It's also the default scope for Spring Beans.

总之,我认为单例比 SLSB Pool 更好,如果可以,你应该使用它。它也是 Spring Beans 的默认范围。

I'm not a JavaEE expert, that's just my feeling, please correct me if I'm wrong.

我不是JavaEE专家,这只是我的感觉,如果我错了,请纠正我。

回答by Yang Lifan

I think you should use Singleton session bean. Because a login service should be a global service and it does not need to store any state for a concrete user or invocation.

我认为您应该使用 Singleton 会话 bean。因为登录服务应该是一个全局服务,它不需要为具体的用户或调用存储任何状态。

回答by Rothron

If you're sure you're not sharing state between threads, then a Singleton will be fine in which case you should also annotate the class with @ConcurrencyManagement( ConcurrencyManagementType.BEAN )which will allow multiple threads running at the same time.

如果您确定不在线程之间共享状态,那么单例就可以了,在这种情况下,您还应该注释@ConcurrencyManagement( ConcurrencyManagementType.BEAN )允许多个线程同时运行的类。

回答by Hammad Dar

you should go for Singleton if you have any resource that is going to remain constant across the application. Like loading some data from some file or reference data which would not change across the application lifecycle. otherwise, go for SLSB. The drawback of SLSB is that multiple objects would be created hence more memory would be occupied.

如果您有任何资源将在整个应用程序中保持不变,您应该选择 Singleton。就像从某个文件中加载一些数据或引用数据一样,这些数据在整个应用程序生命周期中都不会发生变化。否则,请选择 SLSB。SLSB 的缺点是会创建多个对象,因此会占用更多内存。

回答by stephan_bauer

according to the ejb 3.1 spec, page 110, chapter 4.8.5 "Singleton Concurrency":

根据 ejb 3.1 规范,第 110 页,第 4.8.5 章“单例并发”:

It is legal to store Java EE objects that do not support concurrent access (e.g. Entity Managers, Stateful Session Bean references) within Singleton bean instance state. However, it is the responsibility of the Bean Developer to ensure such objects are not accessed by more than one thread at a time.

在单例 bean 实例状态中存储不支持并发访问的 Java EE 对象(例如实体管理器、有状态会话 Bean 引用)是合法的。但是,Bean 开发人员有责任确保一次不会有多个线程访问此类对象。

and furthermore, according to the hibernate entitymanager documentation

此外,根据休眠实体管理器文档

An EntityManager is an inexpensive, non-threadsafe object that should be used once, for a single business process, a single unit of work, and then discarded.

EntityManager 是一个廉价的、非线程安全的对象,应该为单个业务流程、单个工作单元使用一次,然后丢弃。

For me, this means, that you should never inject an EntityManager into a singleton EJB. I would use a singleton EJB as a replacement for a stateless EJB only if EVERYTHING I need to implement in this class supports concurrency without the need to do additional locking / synchronization. As you or other programmers might lose this issue sooner or later from your focus, I personally prefer to not use singleton EJBs except for startup-related issues or features that can be implemented as self-contained units - independently of other beans. In that sense, it doesn't seem to be advisable to inject for example Stateless EJBs into Singletons. Doing so raises the question about the point in time, when the container actually performs the injection of the SLSB into the Singleton? According to the EJB 3.1 Spec, chapter 4.8, the dependency injection gets done before the singleton bean instance can be accessed by clients. So the singleton would obviously stick to the same instance of the SLSB, which seems to become a singleton implicitly, but there doesn't seem to be any guarantee for that. At least I couldn't find anything in the specs, so the behavior might be unpredictable or in the best case container-specific, which is not what most people will want.

对我来说,这意味着永远不要将 EntityManager 注入到单例 EJB 中。仅当我需要在此类中实现的所有内容都支持并发而不需要进行额外的锁定/同步时,我才会使用单例 EJB 作为无状态 EJB 的替代品。由于您或其他程序员迟早会从您的注意力中失去这个问题,因此我个人更喜欢不使用单例 EJB,除非与启动相关的问题或可以作为独立单元实现的功能 - 独立于其他 bean。从这个意义上说,将例如无状态 EJB 注入到单例中似乎并不可取。这样做引发了一个关于时间点的问题,即容器实际将 SLSB 注入到 Singleton 的时间点?根据 EJB 3.1 规范第 4.8 章,依赖注入在客户端可以访问单例 bean 实例之前完成。所以单例显然会坚持 SLSB 的同一个实例,这似乎隐含地变成了单例,但似乎没有任何保证。至少我在规范中找不到任何东西,所以行为可能是不可预测的,或者在最好的情况下是特定于容器的,这不是大多数人想要的。

Thus, I would only inject Singletons into Singletons or Singletons into SLSBs but not vice versa. For the case of an injection of a Singleton into a Singleton, the Spec offers you the opportunity to define the dependencies between the singletons so that the container can initialize them in the correct order (see the ejb 3.1 spec, chapter 4.8.1 concerning the @DependsOn annotation).

因此,我只会将 Singletons 注入 Singletons 或 Singletons 注入 SLSBs,反之亦然。对于将单例注入到单例中的情况,规范为您提供了定义单例之间依赖关系的机会,以便容器可以以正确的顺序初始化它们(参见 ejb 3.1 规范,第 4.8.1 章关于@DependsOn 注释)。

回答by Archimedes Trajano

@Statelesswill allow you to have multiple copies ready for processing within a JVM (as much as memory and pool size allows) where-as @Singleton there's only one copy in a JVM, even if the single one can support multiple concurrent threads running against it.

@Stateless将允许您在 JVM 中准备好多个副本进行处理(内存和池大小允许),其中@Singleton 在 JVM 中只有一个副本,即使单个副本可以支持针对它运行的多个并发线程。

In terms of performance @Singletonwould be better, provided that the resources it uses allow long running access. However, in a distributed environment sometimes bad things occur, e.g. database or network links may fail.

在性能方面@Singleton会更好,前提是它使用的资源允许长时间运行访问。然而,在分布式环境中,有时会发生不好的事情,例如数据库或网络链接可能会失败。

With a @Statelessbean, the access is more short lived. In addition, should there be a failure it will just respawn and try to establish a new connection to the resource. If something happens like that on a singleton, then it's up the the singleton to handle it without requiring an application restart because the @PostConstruct is only called once per JVM.

使用@Statelessbean,访问时间更短。此外,如果出现故障,它将重新生成并尝试与资源建立新连接。如果在单例上发生这样的事情,那么由单例来处理它而不需要重新启动应用程序,因为每个 JVM 只调用一次 @PostConstruct。

I would prefer a bit of fault tolerance vs performance for most situations especially on systems I have no control over.

在大多数情况下,尤其是在我无法控制的系统上,我更喜欢一些容错与性能。

回答by Dirk Schumacher

Imho I would answer like that:

恕我直言,我会这样回答:

"no state has to be shared across the application" leads me to stateless bean because of the sentence "To improve performance, you might choose a stateless session bean...".

“不必在整个应用程序中共享状态”,因为这句话“为了提高性能,您可以选择无状态会话 bean...”,因此我使用了无状态 bean。

Considering "a single enterprise bean could be accessed by multiple threads concurrently" you would have to use singleton. If I got it right it is not even possible to access a stateless bean's concurrently when properly used.

考虑到“单个企业 bean 可以被多个线程同时访问”,您将不得不使用单例。如果我做对了,在正确使用时甚至不可能同时访问无状态 bean。

"no tasks on startup or shotdown need to be performed" would not matter to me. If tasks have to be done to properly setup a bean then they have to be invoked by a @PostActivate method.

“不需要执行启动或击落任务”对我来说无关紧要。如果必须完成任务才能正确设置 bean,则必须通过 @PostActivate 方法调用它们。

I would logically conclude your question what to use to @Singleton since you asked for concurrent access. Of course you will have to manually control snychronisation of accesses on any further resources (which are not EJBs).

自从您要求并发访问以来,我会合乎逻辑地总结您的问题对@Singleton 使用什么。当然,您必须手动控制对任何其他资源(不是 EJB)的访问同步。