7

我有一个使用 spring、hibernate 和 struts 的 Web 应用程序(它在 Tomcat 上运行)

调用顺序是这样的......

Struts 动作调用 spring 服务 bean,后者又调用 Spring DAO bean。DAO 实现是一个 Hibernate 实现。

问题是 我所有的 spring bean 会在同一个线程中运行吗?我可以在 ThreadLocal 中存储一些东西并在另一个 bean 中获取它吗?

我很确定这在无状态会话 Bean 中不起作用。EJB 容器可以(或将)为会话 bean 的每次调用生成一个新线程

弹簧容器会做同样的事情吗?即在同一个线程中运行所有bean?

当我尝试 JUnit 测试时——我通过测试用例中的 Thread.currentThread().getId() 和两个 bean 获得了相同的 id——这让我相信只有一个线程在运行

还是行为不可预测?或者在Tomcat服务器上运行时会改变吗?

澄清 我不希望在两个线程之间交换数据。我想将数据放入 ThreadLocal 并能够从调用堆栈中的所有 bean 中检索它。这只有在所有 bean 都在同一个线程中时才有效

4

4 回答 4

16

Spring 不会产生线程。Tomcat 可以。Spring 只是为您创建和连接对象。

来自浏览器的每个请求都在一个请求中处理。处理请求的是 Tomcat。Tomcat 创建线程来处理请求。

假设您刚刚在 Spring 中创建了一个名为“X”的单例 bean。然后所有请求都使用同一个 X 实例。

Spring bean 并不存在于线程中。它们只是分配在堆上。

于 2009-04-23T16:29:20.053 回答
1

我所有的春豆会在同一个线程中运行吗?我可以在 ThreadLocal 中存储一些东西并在另一个 bean 中获取它吗?AFAIK 对于您提到的组件(服务 bean、DAO bean - 我猜它们是普通的 spring bean),Spring 不会产生新线程。我不了解您的用例(即在两个线程之间交换数据)。

对于大多数 webapps,每个新请求都会产生一个新线程,如果您想在两个请求之间共享数据,您通常: - 使用 get/post 参数来传递数据 - 使用会话来共享数据

要回答您的问题,我很确定 spring 容器不会为大多数组件生成线程。

于 2009-04-23T16:33:11.417 回答
0

是的,你可以这样做。相同的线程将用于执行您的操作,因此 ThreadLocal 将起作用。通常,相同的线程也用于无状态会话 bean,假设它在同一个应用服务器实例中运行。不过,我不会依赖于此,因为它可能取决于供应商。

我们使用这种技术来访问代码中任何地方的调用者身份。我们也使用会话 bean 和 jms,但在容器之间显式传递信息并在每个入口点设置 ThreadLocal。这样,bean(会话或 mdb)是否是本地的都没有关系。

于 2009-04-23T17:27:34.780 回答
0

除了所有其他答案,我将添加以下内容:

通常切换线程的唯一原因是对并行性的某些要求。由于这通常不会在复杂性方面免费提供,因此通常会在发生这种情况时清楚地通知您。

在看似单线程的请求处理中切换线程实际上非常复杂。这通常只会发生在容器中的一个地方,这通常由接收来自外部客户端的请求的 tcp/ip 套接字读取器处理。这些读取器线程通常确定哪个线程(池)应该处理请求并将请求转发到该线程。之后,请求将保留在该线程中。

所以通常唯一会/可能发生的事情是为并行或异步处理(如 JMS)创建额外的线程。

于 2009-04-24T18:48:23.250 回答