访问 线程中的作用域代理 Bean

2022-09-03 03:19:57

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

我猜一定有一种方法可以为每个任务使用弹簧在ThreadPool中注册/取消注册每个线程,但是没有任何运气找到如何做到这一点。

谢谢!


答案 1

我正在将以下超类用于需要访问请求范围的任务。基本上,你可以扩展它并在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();
}

答案 2

我也希望我有1000票给目前接受的答案。一段时间以来,我一直不知道如何做到这一点。基于它,这是我使用可调用界面的解决方案,以防万一你想在Spring 3.0中使用一些新的@Async的东西。

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;
}

推荐