Spring Async,如何在异步任务执行器中启用请求范围

时间:2018-10-01 14:33:21

标签: java spring multithreading spring-boot asynchronous

我尝试使用@Async的despring,在我的服务中,我使用范围为session的bean,总是出现以下错误:

  

org.springframework.beans.factory.BeanCreationException:错误   创建名称为“ scopedTarget.classSession”的bean:   作用域“会话”对当前线程无效;考虑   如果要引用它,则为此bean定义作用域代理   从单身嵌套的异常是java.lang.IllegalStateException:   找不到会话,请求已完成-无法创建新会话   会议!

如前所述,找不到会话,请求已完成。我实现了AsyncConfigurer以便覆盖ThreadPoolTask​​Executor:下面是我的代码

控制器:

@Autowired 
MyService myService;

@RequestMapping(value = "/doIt", method = RequestMethod.PUT)
public HttpEntity initiateCurrent(..){

myService.do();
...
}

MyService

@Autowired 
ClassWithScopeSession classSession;

@Async("taskExecutor")
public void do(){
....
...
classSession.doService();
}

///覆盖ThreadPoolTask​​Executor

public class ContextAwareCallable<T> implements Callable<T> {
    private Callable<T> task;
    private RequestAttributes context;

    @Autowired
    private ApplicationContext appContext;

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

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

@Configuration
@EnableAsync
public class ExecutorConfig  implements AsyncConfigurer {

    @Override
    @Bean(name="taskExecutor")
    public Executor getAsyncExecutor() {
        return new ContextAwarePoolExecutor();
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return null;
    }
}

我遵循了这个response

1 个答案:

答案 0 :(得分:0)

我有一个带有异步方法的多租户应用程序。有人返回 CompletableFuture。 如前所述,现在它对我有用!

@Configuration

@EnableAsync 公共类 DashBoardAsyncExecutorConfig {

@Bean("MyTaskExecutor")
public TaskExecutor taskExecutor() {
    ThreadPoolTaskExecutor executor = new ContextAwarePoolExecutor();
    executor.setCorePoolSize(5);
    executor.setMaxPoolSize(5);
    executor.setQueueCapacity(500);
    executor.setAllowCoreThreadTimeOut(true);
    executor.setThreadNamePrefix("thread");
    executor.initialize();
    return executor;
}

}

公共类 ContextAwarePoolExecutor 扩展了 ThreadPoolTask​​Executor {

   @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()));

   }
   
   //FOR COMPLETABLE FUTURE
   @Override
   public void execute(Runnable task) {
       super.execute(new ContextAwareCallableRunnable(task, RequestContextHolder.currentRequestAttributes()));
   }       

}

public class ContextAwareCallableRunnable<T> implements Runnable {
private Runnable task;
private RequestAttributes context;

public ContextAwareCallableRunnable(Runnable task, RequestAttributes context) {
    this.task = task;
    this.context = context;
}

@Override
public void run() {
    if (context != null) {
        RequestContextHolder.setRequestAttributes(context);
    }
    task.run();
}

}