访问以下线程中的作用域代理 bean

发布于 2024-08-07 02:40:18 字数 304 浏览 6 评论 0原文

我有一个在 tomcat 中运行的 Web 应用程序,其中我使用 ThreadPool (Java 5 ExecutorService) 并行运行 IO 密集型操作以提高性能。我希望每个池线程中使用的一些 bean 位于请求范围内,但 ThreadPool 中的线程无法访问 spring 上下文并获得代理失败。关于如何使 Spring 上下文可供 ThreadPool 中的线程使用以解决代理失败的任何想法吗?

我猜测必须有一种方法可以为每个任务使用 spring 注册/取消注册 ThreadPool 中的每个线程,但还没有找到如何做到这一点的运气。

谢谢!

I have a web application running in tomcat where I'm using a ThreadPool (Java 5 ExecutorService) to run IO intensive operations in parallel to improve performance. I would like to have some of the beans used within each pooled thread be in the request scope, but the Threads in the ThreadPool do not have access to the spring context and get a proxy failure. Any ideas on how to make the spring context available to the threads in the ThreadPool to resolve the proxy failures?

I'm guessing there must be a way to register/unregister each thread in the ThreadPool with spring for each task, but haven't had any luck finding how to do this.

Thanks!

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

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

发布评论

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

评论(4

少跟Wǒ拽 2024-08-14 02:40:18

我正在使用以下超类来执行需要访问请求范围的任务。基本上你可以扩展它并在 onRun() 方法中实现你的逻辑。

import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

/**
 * @author Eugene Kuleshov
 */
public abstract class RequestAwareRunnable implements Runnable {
  private final RequestAttributes requestAttributes;
  private Thread thread;

  public RequestAwareRunnable() {
    this.requestAttributes = RequestContextHolder.getRequestAttributes();
    this.thread = Thread.currentThread();
  }

  public void run() {
    try {
      RequestContextHolder.setRequestAttributes(requestAttributes);
      onRun();
    } finally {
      if (Thread.currentThread() != thread) {
        RequestContextHolder.resetRequestAttributes();
      }
      thread = null;
    }
  }

  protected abstract void onRun();
}

I am using the following super class for my tasks that need to have access to request scope. Basically you can just extend it and implement your logic in onRun() method.

import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

/**
 * @author Eugene Kuleshov
 */
public abstract class RequestAwareRunnable implements Runnable {
  private final RequestAttributes requestAttributes;
  private Thread thread;

  public RequestAwareRunnable() {
    this.requestAttributes = RequestContextHolder.getRequestAttributes();
    this.thread = Thread.currentThread();
  }

  public void run() {
    try {
      RequestContextHolder.setRequestAttributes(requestAttributes);
      onRun();
    } finally {
      if (Thread.currentThread() != thread) {
        RequestContextHolder.resetRequestAttributes();
      }
      thread = null;
    }
  }

  protected abstract void onRun();
}
末骤雨初歇 2024-08-14 02:40:18

我还希望我有 1000 票来支持当前接受的答案。一段时间以来,我一直对如何做到这一点感到困惑。基于此,如果您想在 Spring 3.0 中使用一些新的 @Async 内容,这里是我使用 Callable 接口的解决方案。

public abstract class RequestContextAwareCallable<V> implements Callable<V> {

    private final RequestAttributes requestAttributes;
    private Thread thread;

    public RequestContextAwareCallable() {
        this.requestAttributes = RequestContextHolder.getRequestAttributes();
        this.thread = Thread.currentThread();
    }

    public V call() throws Exception {
        try {
            RequestContextHolder.setRequestAttributes(requestAttributes);
            return onCall();
        } finally {
            if (Thread.currentThread() != thread) {
                RequestContextHolder.resetRequestAttributes();
            }
            thread = null;
        }
    }

    public abstract V onCall() throws Exception;
}

I also wish I had 1000 votes to give to the currently accepted answer. I had been stumped on how to do this for some time. Based on it, here is my solution using the Callable interface in case you want to use some of the new @Async stuff in Spring 3.0.

public abstract class RequestContextAwareCallable<V> implements Callable<V> {

    private final RequestAttributes requestAttributes;
    private Thread thread;

    public RequestContextAwareCallable() {
        this.requestAttributes = RequestContextHolder.getRequestAttributes();
        this.thread = Thread.currentThread();
    }

    public V call() throws Exception {
        try {
            RequestContextHolder.setRequestAttributes(requestAttributes);
            return onCall();
        } finally {
            if (Thread.currentThread() != thread) {
                RequestContextHolder.resetRequestAttributes();
            }
            thread = null;
        }
    }

    public abstract V onCall() throws Exception;
}
回忆那么伤 2024-08-14 02:40:18

你能反过来试试吗?使用存储在请求范围中的数据容器并将其提供给线程池(也许将其放入队列中,以便线程池可以一次获取一个数据容器,对其进行处理,将其标记为“完成”并继续与下一个)。

Could you try it the other way round? Use a data container that's stored in request scope and give it to the thread pool (perhaps put it into a queue, so that the thread pool can take one data container at a time, work on it, mark it as "done" and continue with the next one).

无风消散 2024-08-14 02:40:18

Spring 有一个 ThreadPoolTask​​Executor可用于从 Spring 管理线程池的类。然而,看起来您必须做一些工作才能使 Spring 上下文可供每个线程使用。

即使您以这种方式连接,我也不确定它是否会起作用。 Spring 在本地线程中使用令牌来定位请求(或会话)作用域中的对象,因此如果您尝试从不同的线程访问请求作用域 bean,则该令牌可能不存在。

Spring has a ThreadPoolTaskExecutor class that you can use to manage your thread pool from Spring. However, it looks like you'd have to do some work to make the Spring context available to each thread.

I'm not sure if it will work even if you do wire it up this way though. Spring uses a token in thread local to locate objects in request (or session) scope, so if you're trying to access a request scope bean from a different thread, it's likely that token won't be there.

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