2017-10-19 157 views
0

我使用Spring的@EnableAsync功能来异步执行方法。为了安全,我使用Apache Shiro。在异步执行的代码中,我需要访问附加到触发异步调用的线程的Shiro主题。自定义/扩展Spring对于shiro的@Async支持

四郎支持与Callable就是要在不同的线程中执行对象关联使用在不同的线程现有的内容(见here):

Subject.associateWith(Callable) 

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

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

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

我会很好地添加一个新的自定义异步注释。但我认为这不会有什么帮助。


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

+0

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

回答

1

我设法达到我想要的 - 四郎主题是由Spring的异步支持执行的任务自动绑定和非绑定 - 通过提供ThreadPoolTaskExecutor的扩展版本:

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 
} 

为了使弹簧使用该我执行人必须实现一个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和 - 可能更加重要 - 在执行异步方法后,主题将从线程中解除。