javascript
Spring @Async注解
1.@Async注解使用條件
@Async源碼- @Async注解一般用在類的方法上,如果用在類上,那么這個類所有的方法都是異步執(zhí)行的;
- 所使用的@Async注解方法的類對象應(yīng)該是Spring容器管理的bean對象;
- 調(diào)用異步方法類上需要配置上注解@EnableAsync
2.實現(xiàn)原理
為了更基礎(chǔ)的分析異步調(diào)用背后的實現(xiàn)原理,這里選擇使用xml配置文件的方式。使用xml配置文件方式時,一般會配置如下元素:
<task:annotation-driven executor="myExecutor" exception-handler="exceptionHandler"/> <task:executor id="myExecutor" pool-size="5"/> <bean id="exceptionHandler" class="com.abc.MyAsynExceptionHandler"/>2.1 task標簽
一般對于這種標簽的解析都會有相應(yīng)的NamespaceHandler,根據(jù)Spring命名的套路查找TaskNamespaceHandler類,具體代碼如下:
TaskNamespaceHandler(1)executor元素對應(yīng)的ExecutorBeanDefinitionParser
ExecutorBeanDefinitionParser該類從parse方法追蹤具體的實現(xiàn)邏輯,這個類主要是根據(jù)executor元素中的配置,例如pool-size創(chuàng)建一個TaskExecutorFactoryBean對象,而在TaskExecutorFactoryBean中間接使用ThreadPoolExecutor創(chuàng)建了一個線程池,這個線程池會在annotation-driven元素解析類中用到。
在TaskExecutorFactoryBean中可以看出:
TaskExecutorFactoryBean(2)annotation-driven元素處理類AnnotationDrivenBeanDefinitionParser
AnnotationDrivenBeanDefinitionParser默認情況下,如果沒有配置mode屬性,其值默認是proxy,使用代理模式,會創(chuàng)建一個AsyncAnnotationBeanPostProcessor,然后解析executor屬性值和exception-handler屬性值并將其設(shè)置到AsyncAnnotationBeanPostProcessor中。
該類實現(xiàn)了BeanFactoryAware接口,所以在其實例化時會執(zhí)行setBeanFactory方法:
創(chuàng)建AsyncAnnotationAdvisor對象,即給線程池創(chuàng)建了一個異步注解切面
AsyncAnnotationAdvisor主要就是使用上面提到的executor元素解析得到的線程池和異常處理創(chuàng)建通知,使用@Async注解創(chuàng)建切入點
進入構(gòu)建通知的方法中,buildAdvice(executor, exceptionHandler)
AnnotationAsyncExecutionInterceptor間接實現(xiàn)了MethodInterceptor接口,而MethodInterceptor是AOP中切入點的處理器,處理器中最終被調(diào)用的是invoke方法,下面是invoke方法的源碼:
AsyncExecutionInterceptordoSubmit方法源碼:
AsyncExecutionAspectSupportAsyncAnnotationBeanPostProcessor類還間接實現(xiàn)了BeanPostProcessor接口,也就是說在bean初始化之前和之后會分別執(zhí)行postProcessBeforeInitialization方法和postProcessAfterInitialization方法,而AsyncAnnotationBeanPostProcessor類的這兩個方法是從AbstractAdvisingBeanPostProcessor類中繼承來的,這里重點分析postProcessAfterInitialization方法,具體代碼如下:
AbstractAdvisingBeanPostProcessor創(chuàng)建代理可以使用Cglib或者jdk動態(tài)代理,這里選擇JdkDynamicAopProxy深入分析,代理的創(chuàng)建這里就不深入分析了,這里重點關(guān)注一下調(diào)用代理時真正執(zhí)行的invoke方法,方法體內(nèi)容比較多,這里看一下如下重要代碼:
JdkDynamicAopProxy?
總結(jié)
Spring容器啟動初始化bean時,判斷類中是否使用了@Async注解,創(chuàng)建切入點和切入點處理器,根據(jù)切入點創(chuàng)建代理,在調(diào)用@Async注解標注的方法時,會調(diào)用代理,執(zhí)行切入點處理器invoke方法,將方法的執(zhí)行提交給線程池,實現(xiàn)異步執(zhí)行。
所以,需要注意的一個錯誤用法是,如果A類的a方法(沒有標注@Async)調(diào)用它自己的b方法(標注@Async)是不會異步執(zhí)行的,因為從a方法進入調(diào)用的都是它本身,不會進入代理
作者:LZhan
鏈接:https://www.jianshu.com/p/69a7bbdaceeb
來源:簡書
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。
總結(jié)
以上是生活随笔為你收集整理的Spring @Async注解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如果张东升是个程序员
- 下一篇: Spring杂谈 | 什么是Object