我们遇到了同样的问题-需要使用@Async在后台执行代码,因此它无法使用任何Session-或RequestScope bean。我们通过以下方式解决了它:
- 创建一个自定义TaskPoolExecutor,用于存储范围内的信息和任务
- 创建一个特殊的Callable(或Runnable),该信息使用该信息来设置和清除后台线程的上下文
- 创建替代配置以使用自定义执行程序
注意:这仅适用于Session和Request作用域的bean,不适用于安全上下文(如Spring Security中一样)。如果您要这样做,则必须使用另一种方法来设置安全上下文。
注意2:为简便起见,仅显示Callable和Submit()实现。您可以对Runnable和execute()执行相同的操作。
这是代码:
Executor:
public class ContextAwarePoolExecutor extends ThreadPoolTaskExecutor { @Override public <T> Future<T> submit(Callable<T> task) { return super.submit(new ContextAwareCallable(task, RequestContextHolder.currentRequestAttributes())); } @Override public <T> ListenableFuture<T> submitListenable(Callable<T> task) { return super.submitListenable(new ContextAwareCallable(task, RequestContextHolder.currentRequestAttributes())); }}Callable:
public class ContextAwareCallable<T> implements Callable<T> { private Callable<T> task; private RequestAttributes context; public ContextAwareCallable(Callable<T> task, RequestAttributes context) { this.task = task; this.context = context; } @Override public T call() throws Exception { if (context != null) { RequestContextHolder.setRequestAttributes(context); } try { return task.call(); } finally { RequestContextHolder.resetRequestAttributes(); } }}Configuration:
@Configurationpublic class ExecutorConfig extends AsyncConfigurerSupport { @Override @Bean public Executor getAsyncExecutor() { return new ContextAwarePoolExecutor(); }}


