【问题标题】:Customize/Extend Spring's @Async support for shiro自定义/扩展 Spring 对 shiro 的 @Async 支持
【发布时间】:2018-03-31 12:19:14
【问题描述】:

我正在使用 Spring 的 @EnableAsync 功能来异步执行方法。为了安全起见,我使用的是 Apache Shiro。在异步执行的代码中,我需要访问附加到触发异步调用的线程的 Shiro 主题。

Shiro 支持在不同线程中使用现有主题,方法是将主题与要在不同线程上执行的 Callable 相关联(参见 here):

Subject.associateWith(Callable)

不幸的是,我无法直接访问Callable,因为这些东西是由 Spring 封装的。我发现我需要扩展 Spring 的 AnnotationAsyncExecutionInterceptor 以将我的主题与创建的 Callable 相关联(这是最简单的部分)。

现在的问题是如何让 Spring 使用我的自定义 AnnotationAsyncExecutionInterceptor 而不是默认的。默认是在AsyncAnnotationAdvisorAsyncAnnotationBeanPostProcessor 中创建的。我当然也可以扩展这些类,但这只会转移到问题,因为我需要让 Spring 再次使用我的扩展类。

有什么方法可以实现我想要的吗?

我也可以添加一个新的自定义异步注释。但我认为这不会有太大帮助。


更新: 实际上我发现AnnotationAsyncExecutionInterceptor 需要定制是错误的。偶然我偶然发现了org.apache.shiro.concurrent.SubjectAwareExecutorService,它完全符合我的要求,让我觉得我可以简单地提供一个自定义执行器而不是自定义拦截器。详情见我的回答。

【问题讨论】:

  • 您是否可以选择:1 重写您的“异步方法”以返回 Callables 2. 手动启动 (call())(在弹簧配置的 executionPool 中)

标签: java spring asynchronous shiro


【解决方案1】:

通过提供ThreadPoolTaskExecutor 的扩展版本,我设法实现了我想要的 - shiro 主题自动绑定和解除绑定到由 spring 的异步支持执行的任务:

public class SubjectAwareTaskExecutor extends ThreadPoolTaskExecutor {

  @Override
  public void execute(final Runnable aTask) {
    final Subject currentSubject = ThreadContext.getSubject();
    if (currentSubject != null) {
      super.execute(currentSubject.associateWith(aTask));
    } else {
      super.execute(aTask);
    }
  }

  ... // override the submit and submitListenable method accordingly
}

为了让 spring 使用这个执行器,我必须实现一个 AsyncConfigurer 来返回我的自定义执行器:

@EnableAsync
public class AsyncConfiguration implements AsyncConfigurer {

  @Override
  public Executor getAsyncExecutor() {
    final SubjectAwareTaskExecutor executor = new SubjectAwareTaskExecutor();
    executor.setBeanName("async-executor");
    executor.setCorePoolSize(10);
    executor.setMaxPoolSize(10);
    executor.initialize();
    return executor;
  }

  @Override
  public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
    return new SimpleAsyncUncaughtExceptionHandler();
  }
}

通过此更改,父线程的主题将自动在带有 @Async 注释的方法中可用,并且 - 可能更重要的是 - 在执行异步方法后主题将与线程分离。

【讨论】:

  • 分享您的解决方案!
猜你喜欢
  • 2018-12-08
  • 2020-11-18
  • 2016-12-21
  • 2022-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-06
相关资源
最近更新 更多