2017-10-19 42 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和 - 可能更加重要 - 在執行異步方法後,主題將從線程中解除。