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

发布于 2024-08-17 03:47:51 字数 1056 浏览 7 评论 0原文

Java EE 6 教程 说:

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

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

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

  • 状态需要在应用程序之间共享。
  • 单个企业 Bean 需要由多个线程同时访问。
  • 应用程序需要企业 Bean 来在应用程序启动和关闭时执行任务。
  • Bean 实现 Web 服务。

但是,如果出现以下情况,应该使用什么:

  • 不需要在应用程序之间共享状态
  • 单个企业 bean 可以由多个线程同时访问
  • 不需要执行启动或关闭时的任务

比如说,我有一个具有以下接口的登录服务:

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

应该它是用@Singleton还是@Stateless注释的?两者各有什么好处?如果 LoginService 需要注入 EntityManager(将同时使用)怎么办?

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

The Java EE 6 Tutorial says:

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.

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

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)?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

红颜悴 2024-08-24 03:47:51

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

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

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

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.

尾戒 2024-08-24 03:47:51

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

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

此外,根据 hibernate entitymanager 文档

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

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

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

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

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.

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.

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.

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).

羁绊已千年 2024-08-24 03:47:51

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

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

使用@Stateless bean,访问的生命周期更短。此外,如果出现故障,它将重新生成并尝试与资源建立新的连接。如果在单例上发生类似的情况,则由单例来处理它,而不需要重新启动应用程序,因为每个 JVM 只调用 @PostConstruct 一次。

对于大多数情况,特别是在我无法控制的系统上,我更喜欢一点容错性而不是性能。

@Stateless will 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.

In terms of performance @Singleton would 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.

With a @Stateless bean, 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.

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

香橙ぽ 2024-08-24 03:47:51

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

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

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

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.

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.

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

野味少女 2024-08-24 03:47:51

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

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.

我的痛♀有谁懂 2024-08-24 03:47:51

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

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.

眼前雾蒙蒙 2024-08-24 03:47:51

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

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.

箹锭⒈辈孓 2024-08-24 03:47:51

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

“没有状态必须在应用程序中共享”导致我使用无状态 bean,因为“为了提高性能,您可以选择无状态会话 bean...”。

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

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

我会从逻辑上总结你的问题,因为你要求并发访问,所以要使用@Singleton。当然,您必须手动控制对任何其他资源(不是 EJB)的访问同步。

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...".

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.

"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.

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).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文