不僅會用@Async,我把源碼也梳理了一遍(下)
- 2019 年 10 月 8 日
- 筆記

終於到了源碼分析的環節了,在這之前我已經寫過了兩篇文章專門分析這個@Async了,還沒看過的同學先去看下哈。
好了,不啰嗦。
分析過程:
- 開啟非同步代理
- 初始化excutor和exceptionHandler
- 定義切面處理
- 執行緒處理
開啟非同步化支援
@EnableAsync
@EnableAsync是開啟某個模組的功能載入,之前在《導圖梳理springboot手動、自動裝配,讓springboot不再難懂》介紹過,@EnableXXX一般都有兩種用法,一種直接引入配置,一種可以通過註解的元數據選擇需要導入的配置。這裡的@EnableAsync明顯屬於第二種。
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(AsyncConfigurationSelector.class) public @interface EnableAsync { // 默認是@Async和EJB3.1規範下的@Asynchronous註解, // 這裡表示可以自定義註解啟動非同步 Class<? extends Annotation> annotation() default Annotation.class; // true表示啟用CGLIB代理 boolean proxyTargetClass() default false; // 切面通知模式:默認動態代理PROXY AdviceMode mode() default AdviceMode.PROXY; int order() default Ordered.LOWEST_PRECEDENCE; }
這個EnableAsync註解,一般註解屬性我們都不需要改,默認就行了。那麼這裡最重要的程式碼就只有一行了,就是這個@Import(AsyncConfigurationSelector.class),導入AsyncConfigurationSelector配置。
AsyncConfigurationSelector
我們打開AsyncConfigurationSelector看看:
/* * 關鍵點: * 1、父類AdviceModeImportSelector * 2、導入配置類ProxyAsyncConfiguration * */ public class AsyncConfigurationSelector extends AdviceModeImportSelector<EnableAsync> { private static final String ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME = "org.springframework.scheduling.aspectj.AspectJAsyncConfiguration"; @Override @Nullable public String[] selectImports(AdviceMode adviceMode) { switch (adviceMode) { case PROXY: return new String[] {ProxyAsyncConfiguration.class.getName()}; case ASPECTJ: return new String[] {ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME}; default: return null; } } }
上面的源碼裡面,我在開頭寫了2個關鍵點,
- 一個是父類AdviceModeImportSelector
- 二是導入配置類ProxyAsyncConfiguration
大家在源碼分析的時候這樣去看源碼,當你打開一個類的時候,裡面有很多個方法,你不知道你應該從哪個方法看起,你第一時間可以先去看繼承關係,就比如這AsyncConfigurationSelector類,他繼承了AdviceModeImportSelector,但AdviceModeImportSelector其實又實現了ImportSelector,而ImportSelector是我們比較熟悉的介面。我們知道ImportSelector裡面有個方法selectImports(AnnotationMetadata)是用於根據註解屬性導入配置的,所以這裡就是我們的突破口。
所以綜合來看源碼的方法是這樣的:
當你打開一個類,比較迷茫的時候:
- 第一步:打開類的繼承關係圖(Ctrl+Shift+Alt+u)

找你熟悉的一些介面,如果是Spring,特別需要注意spring的Aware系列介面,比如:
- BeanNameAware :可以獲取容器中bean的名稱
- BeanFactoryAware:獲取當前bean factory這也可以調用容器的服務
- ApplicationContextAware:當前的applicationContext, 這也可以調用容器的服務
- MessageSourceAware:獲得message source,這也可以獲得文本資訊
- applicationEventPulisherAware:應用事件發布器,可以發布事件,
- ResourceLoaderAware:獲得資源載入器,可以獲得外部資源文件的內容;
這些都有一些特殊的功能,在spring項目被啟動的時候會被調用對應的實現介面,所以看到這些Aware實現類的時候,如果你比較迷茫,可以從Aware的實現類的介面重寫開始看。
而剛才我們說到的ImportSelector也是spring的一個比較特殊的介面了,我們就從selectImports(AnnotationMetadata)方法看起:
public abstract class AdviceModeImportSelector<A extends Annotation> implements ImportSelector { public static final String DEFAULT_ADVICE_MODE_ATTRIBUTE_NAME = "mode"; protected String getAdviceModeAttributeName() { return DEFAULT_ADVICE_MODE_ATTRIBUTE_NAME; } @Override public final String[] selectImports(AnnotationMetadata importingClassMetadata) { Class<?> annType = GenericTypeResolver.resolveTypeArgument(getClass(), AdviceModeImportSelector.class); Assert.state(annType != null, "Unresolvable type argument for AdviceModeImportSelector"); // 獲取@EnableAsync的屬性值 AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType); if (attributes == null) { throw new IllegalArgumentException(String.format( "@%s is not present on importing class '%s' as expected", annType.getSimpleName(), importingClassMetadata.getClassName())); } AdviceMode adviceMode = attributes.getEnum(getAdviceModeAttributeName()); // 調用抽象方法,由子類重寫 String[] imports = selectImports(adviceMode); if (imports == null) { throw new IllegalArgumentException("Unknown AdviceMode: " + adviceMode); } return imports; } /** * 由子類AsyncConfigurationSelector重寫了這個方法 */ @Nullable protected abstract String[] selectImports(AdviceMode adviceMode); }
所以從這個方法看起你就很容易梳理到程式碼了。上面程式碼中,首先把EnableAsync的元數據都封裝到AnnotationAttributes中,然後再獲取到AdviceMode,最後選擇出需要導入的配置,而導入的配置方法是個抽象方法selectImports(AdviceMode),由子類重寫。子類自然就是AsyncConfigurationSelector,所以你才可以看到AsyncConfigurationSelector里有個selectImports方法,其實是重寫了父類的。
現在邏輯相對清晰了,由於AdviceMode默認就是AdviceMode.PROXY,所以我們導入的配置就是ProxyAsyncConfiguration,接下來我們再去分析。
ProxyAsyncConfiguration
這看配置類的名稱,翻譯過來就是代理非同步配置。有時候我們看源碼也要從一個類的名稱去猜測可能的功能。我們之前在第二篇文章中猜想過,應該有個Aop切面處理@Async註解,如果大家熟悉aop的原理的話,aop也是使用的了代理。那麼應該就是在這個配置類裡面實現的了。
好了,由一個名字我想了這麼多,接下來先看下程式碼:
/* * 這裡的關鍵點有2個: * 1、父類AbstractAsyncConfiguration * 2、初始化對象AsyncAnnotationBeanPostProcessor * */ @Configuration @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public class ProxyAsyncConfiguration extends AbstractAsyncConfiguration { @Bean(name = TaskManagementConfigUtils.ASYNC_ANNOTATION_PROCESSOR_BEAN_NAME) @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public AsyncAnnotationBeanPostProcessor asyncAdvisor() { Assert.notNull(this.enableAsync, "@EnableAsync annotation metadata was not injected"); AsyncAnnotationBeanPostProcessor bpp = new AsyncAnnotationBeanPostProcessor(); bpp.configure(this.executor, this.exceptionHandler); // 自定義的非同步註解 Class<? extends Annotation> customAsyncAnnotation = this.enableAsync.getClass("annotation"); if (customAsyncAnnotation != AnnotationUtils.getDefaultValue(EnableAsync.class, "annotation")) { bpp.setAsyncAnnotationType(customAsyncAnnotation); } bpp.setProxyTargetClass(this.enableAsync.getBoolean("proxyTargetClass")); bpp.setOrder(this.enableAsync.<Integer>getNumber("order")); return bpp; } }
上面我依然點出了兩個重點:
- 1、父類AbstractAsyncConfiguration
- 2、初始化對象AsyncAnnotationBeanPostProcessor 為什麼一直強調父類,因為子類初始化之前,父類是要先完成初始化的,所以載入順序都是父類先載入,這點必須清楚,另外就是子類一般都要重寫父類的方法,重寫的方法一般在父類的其他方法中會被調用。
既然是繼承關係,我們依然來看下繼承關係圖:

上面我們就看到了上面我說過的Aware系列的介面之一ImportAware,作用是通過實現ImportAware介面獲取對應註解的元數據。
所以,我們先去看完父類AbstractAsyncConfiguration,然後再回頭來看子類ProxyAsyncConfiguration。
@Configuration public abstract class AbstractAsyncConfiguration implements ImportAware { @Nullable protected AnnotationAttributes enableAsync; @Nullable protected Supplier<Executor> executor; @Nullable protected Supplier<AsyncUncaughtExceptionHandler> exceptionHandler; /** * 通過實現ImportAware介面獲取@EnableAsync的屬性值 * @param importMetadata */ @Override public void setImportMetadata(AnnotationMetadata importMetadata) { this.enableAsync = AnnotationAttributes.fromMap( importMetadata.getAnnotationAttributes(EnableAsync.class.getName(), false)); if (this.enableAsync == null) { throw new IllegalArgumentException( "@EnableAsync is not present on importing class " + importMetadata.getClassName()); } } /** * Collect any {@link AsyncConfigurer} beans through autowiring. * * 導入自定義的實現了AsyncConfigurer介面的bean * 並給executor、exceptionHandler附上自定義的值 * */ @Autowired(required = false) void setConfigurers(Collection<AsyncConfigurer> configurers) { // 如果沒有自定義實現AsyncConfigurer介面,直接返回 if (CollectionUtils.isEmpty(configurers)) { return; } if (configurers.size() > 1) { throw new IllegalStateException("Only one AsyncConfigurer may exist"); } // 有的話,直接賦值 AsyncConfigurer configurer = configurers.iterator().next(); this.executor = configurer::getAsyncExecutor; this.exceptionHandler = configurer::getAsyncUncaughtExceptionHandler; } }
1、setImportMetadata方法里讀取了EnableAsync的元數據存在了AnnotationAttributes 中。2、setConfigurers導入自定義的AsyncConfigurer配置類。
我們在第一篇文中就自定義了執行緒池,還有非同步執行緒的錯誤處理器等,就是通過實現AsyncConfigurer介面實現的,而我們自定義的類就會被注入到setConfigurers這個方法中,然後被賦值給當前類的executor和exceptionHandler。
所以這個父類中,其實就是一些初始化,初始化this.enableAsync、this.executor和this.exceptionHandler。
當然了,我們不是必須要實現AsyncConfigurer重寫executor和exceptionHandler,所以this.executor和this.exceptionHandler可能還是為null的。
我們再回到ProxyAsyncConfiguration的asyncAdvisor()方法,看這個方法名稱,有點非同步切面的意思呀,那麼返回值AsyncAnnotationBeanPostProcessor是否就是一個切面增強類呢?這個我們去看下繼承關係。

繼承的東西比較多,先來說說我們比較熟悉的東西:
- BeanClassLoaderAware – 獲取當前類的類載入器
- BeanFactoryAware – 獲取Spring的核心容器BeanFactory
- BeanPostProcessor – bean初始化過程中的前置、後置處理器
- AbstractAdvisingBeanPostProcessor – 生成aop代理的後置處理器
那麼現在來梳理一下邏輯,首先ProxyAsyncConfiguration中會開始初始化AsyncAnnotationBeanPostProcessor,因為是@Bean,所以在對象注入spring容器之前,你先不用看aware系列,不用看BeanPostProcessor,先看@Bean裡面方法的內容,那是注入spring容器之前可能做一些初始化。
而asyncAdvisor()方法中,關鍵的程式碼其實也沒多少,邏輯如下:1、就是new一個AsyncAnnotationBeanPostProcessor對象 2、bpp.configure(this.executor, this.exceptionHandler);就是賦值excutor和exceptionHandler:
- AsyncAnnotationBeanPostProcessor#configure
public void configure( @Nullable Supplier<Executor> executor, @Nullable Supplier<AsyncUncaughtExceptionHandler> exceptionHandler) { this.executor = executor; this.exceptionHandler = exceptionHandler; }
3、bpp.setAsyncAnnotationType(customAsyncAnnotation);如果有自定義的非同步註解就賦值
然後就返回了對象,通過@Bean註解,這時候這個new出來的AsyncAnnotationBeanPostProcessor對象就會注入到spring容器中,進而調用aware和beanPostProcessor那一套流程。
AsyncAnnotationBeanPostProcessor
接下來就是重點之中的重點了,可以說@Async的重點核心就是這個類,之前做了這麼多準備就是為了初始化這個類。
我們來回顧一下上面的內容,首先我們獲得了自定義的excutor和exceptionHandler,然後新建了AsyncAnnotationBeanPostProcessor對象並注入到了spring容器中,因為bean的生命周期比較複雜。
我怕很多人沒研究過spring的容器,對spring bean的聲明周期不太了解,特意從網上找了一張總結的圖,讓大家一張圖搞懂Spring bean的生命周期,從Spring容器啟動到容器銷毀bean的全過程。

通過這個圖,我們再回到我們的這個AsyncAnnotationBeanPostProcessor這個類的繼承關係圖,你就知道了執行的順序流程如下:
- 1、因為實現了BeanPostProcessor,所以先執行postProcessBeforeInitialization
- 2、執行構造器方法
- 3、執行BeanFactoryAware 、BeanClassLoaderAware的對應方法
- 4、執行BeanPostProcessor的postProcessAfterInitialization方法
ok,順序已給出,那麼初始化的過程就清晰了,接下來我們只需要一步一步去看對應模組的程式碼。
- 第一步:postProcessBeforeInitialization 好像啥都沒做,忽略
@Override public Object postProcessBeforeInitialization(Object bean, String beanName) { return bean; }
- 第二步:構造器
其實對象我們是new出來的,然後再通過@Bean注入容器的,並不是使用@Component或者xml方式注入,所以構造器應該是早就執行了
public AsyncAnnotationBeanPostProcessor() { setBeforeExistingAdvisors(true); }
這個構造器只有一行程式碼,是說是不是在其他已存在的aop之前執行,參數表示是的。
- 第三步:BeanClassLoaderAware、BeanFactoryAware
因為BeanClassLoaderAware是aop程式碼部分的了,是為了給對象生成代理的時候統一類載入器。所以這個方法我們不需要看。
我們來看下BeanFactoryAware的setBeanFactory方法:
- AsyncAnnotationBeanPostProcessor#setBeanFactory
@Override public void setBeanFactory(BeanFactory beanFactory) { super.setBeanFactory(beanFactory); /** * 創建切面處理 */ AsyncAnnotationAdvisor advisor = new AsyncAnnotationAdvisor(this.executor, this.exceptionHandler); if (this.asyncAnnotationType != null) { advisor.setAsyncAnnotationType(this.asyncAnnotationType); } advisor.setBeanFactory(beanFactory); this.advisor = advisor; }
程式碼中,除了引入beanFactory之外,還定義了一個切面advisor ,並把切面advisor賦值給當前對象。
我們中篇文中說過,用編碼實現一個aop,需要準備幾個東西:
- ProxyFactory 代理工廠
- Pointcut 切點
- Advice 通知
- Advisor 切面
- Target 被代理對象
有了這幾個組件之後,我們就可以構建成一個aop。
那麼再看這裡程式碼,這裡的advisor就在這裡初始化獲取到了。而我們可以這樣理解:Advisor = pointcut + Advice ,所以可說,我們完成了切面的初始化,其實也是@Async核心重要的一部分了。
ok,有了知識儲備,搞啥都清晰。我們接著往下面走, 看AsyncAnnotationAdvisor的初始化過程先,也就是構造方法:
public AsyncAnnotationAdvisor( @Nullable Supplier<Executor> executor, @Nullable Supplier<AsyncUncaughtExceptionHandler> exceptionHandler) { Set<Class<? extends Annotation>> asyncAnnotationTypes = new LinkedHashSet<>(2); asyncAnnotationTypes.add(Async.class); try { asyncAnnotationTypes.add((Class<? extends Annotation>) ClassUtils.forName("javax.ejb.Asynchronous", AsyncAnnotationAdvisor.class.getClassLoader())); } catch (ClassNotFoundException ex) { // If EJB 3.1 API not present, simply ignore. } this.advice = buildAdvice(executor, exceptionHandler); this.pointcut = buildPointcut(asyncAnnotationTypes); }
上面重點是這兩行:
this.advice = buildAdvice(executor, exceptionHandler); this.pointcut = buildPointcut(asyncAnnotationTypes);
切面等於切點加通知處理。就是這兩樣東西了。也就是構造器裡面其實得到了切點和通知。接下來我們繼續看著兩個方法:
- AsyncAnnotationAdvisor#buildAdvice
protected Advice buildAdvice( @Nullable Supplier<Executor> executor, @Nullable Supplier<AsyncUncaughtExceptionHandler> exceptionHandler) { AnnotationAsyncExecutionInterceptor interceptor = new AnnotationAsyncExecutionInterceptor(null); interceptor.configure(executor, exceptionHandler); return interceptor; }
我們先來看下AnnotationAsyncExecutionInterceptor的繼承關係:

這裡面我們比較熟悉的類有Advice、Interceptor、BeanFactoryAware。結合第二篇文章中講到的生成aop的編碼實現。你基本可以確定,這個AnnotationAsyncExecutionInterceptor類就是我們環繞通知的處理類了,Advice說明了這個類是個aop通知處理類,Interceptor說明了處理的方法是攔截器的invoke方法。切面攔截到切點時候就會到這個方法的invoke中執行對應的業務處理邏輯。
那麼對應到@Async,執行的邏輯應該就是起一個執行緒執行方法。
清楚了這一點之後,我們再回到AnnotationAsyncExecutionInterceptor構造方法中,最終調用的是父類中的構造方法:
public AsyncExecutionAspectSupport(@Nullable Executor defaultExecutor) { this.defaultExecutor = new SingletonSupplier<>(defaultExecutor, () -> getDefaultExecutor(this.beanFactory)); this.exceptionHandler = SingletonSupplier.of(SimpleAsyncUncaughtExceptionHandler::new); }
這裡就是給executor和exceptionHandler一個初始化的執行器或錯誤處理器,初始化默認處理器之後再執行interceptor.configure(executor, exceptionHandler);
public void configure(@Nullable Supplier<Executor> defaultExecutor, @Nullable Supplier<AsyncUncaughtExceptionHandler> exceptionHandler) { this.defaultExecutor = new SingletonSupplier<>(defaultExecutor, () -> getDefaultExecutor(this.beanFactory)); this.exceptionHandler = new SingletonSupplier<>(exceptionHandler, SimpleAsyncUncaughtExceptionHandler::new); }
這意思就是如果我們之前自定義了執行器和錯誤處理器,那麼用我們自定義的,如果沒有就用剛剛在構造器中初始化的默認的。
所以,切面的環繞通知處理Advice已經生成。我們再來看看另一個方法
- AsyncAnnotationAdvisor#buildPointcut
protected Pointcut buildPointcut(Set<Class<? extends Annotation>> asyncAnnotationTypes) { ComposablePointcut result = null; for (Class<? extends Annotation> asyncAnnotationType : asyncAnnotationTypes) { Pointcut cpc = new AnnotationMatchingPointcut(asyncAnnotationType, true); Pointcut mpc = new AnnotationMatchingPointcut(null, asyncAnnotationType, true); if (result == null) { result = new ComposablePointcut(cpc); } else { result.union(cpc); } result = result.union(mpc); } return (result != null ? result : Pointcut.TRUE); }
這生成切點的邏輯也挺簡單的,之前允許在@EnableAsync中通過annatation定義自定義的非同步執行緒註解,我們常用的默認是@Async。所以這裡意思其實是把所有的可能的註解都union起來,union就是合併意思。不管自定義的,還是默認的都作為切點。
這時候切點Pointcut已初始化好。
所以在AsyncAnnotationAdvisor中我們初始化好了Advice和Pointcut,而切面就等於Advice+Pointcut,那麼它是一個切面來的嗎?我們來看下繼承關係:

果然實現了Advisor,是個切面。所以致此,我們已經定義了一個切面。
- 第四步:執行BeanPostProcessor的postProcessAfterInitialization方法
上面三步走完之後,我們定義得到了一個切面,接下來我們進入最後一步,就是bean的後置處理,這個後置處理器其實是aop中實現的,所以我們定義一個aop切面,其實都需要進入這個後置處理器,那麼這裡面做了什麼事情呢?
@Override public Object postProcessAfterInitialization(Object bean, String beanName) { if (this.advisor == null || bean instanceof AopInfrastructureBean) { // Ignore AOP infrastructure such as scoped proxies. return bean; } if (bean instanceof Advised) { Advised advised = (Advised) bean; if (!advised.isFrozen() && isEligible(AopUtils.getTargetClass(bean))) { // Add our local Advisor to the existing proxy's Advisor chain... if (this.beforeExistingAdvisors) { advised.addAdvisor(0, this.advisor); } else { advised.addAdvisor(this.advisor); } return bean; } } if (isEligible(bean, beanName)) { ProxyFactory proxyFactory = prepareProxyFactory(bean, beanName); if (!proxyFactory.isProxyTargetClass()) { evaluateProxyInterfaces(bean.getClass(), proxyFactory); } proxyFactory.addAdvisor(this.advisor); customizeProxyFactory(proxyFactory); return proxyFactory.getProxy(getProxyClassLoader()); } // No proxy needed. return bean; }
看了裡面的邏輯,應該就是直接給bean生成代理的了,那麼我們寫的Async程式碼中,那些需要我們生成代理呢,是不是所有寫了@Async註解的方法或者類?因為我知道aop通過ProxyFactory生成代理的,所以我在 ProxyFactory proxyFactory = prepareProxyFactory(bean, beanName); 這裡打個端點,然後啟動項目。

果然,需要代理的是UserServiceImpl,因為我的@Async方法都是寫在UserServiceImpl上的:

所以UserServiceImpl就是aop需要代理的對象。其中prepareProxyFactory的程式碼如下:
protected ProxyFactory prepareProxyFactory(Object bean, String beanName) { ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.copyFrom(this); proxyFactory.setTarget(bean); return proxyFactory; }
就是創建proxyFactory對象,然後設置目標代理對象就是UserServiceImpl,然後接著走是設置interface的,
if (!proxyFactory.isProxyTargetClass()) { evaluateProxyInterfaces(bean.getClass(), proxyFactory); }
其中evaluateProxyInterfaces的內容是:

可以看到因為UserServiceImpl是個實現類,所以對應的介面需要聲明,這樣使用UserService調用方法時候才會觸發aop。所以這裡面的重要程式碼就是proxyFactory.addInterface(ifc);
然後方法繼續執行,就到了proxyFactory.addAdvisor(this.advisor);這一句,advisor就是我們上面初始化好的切面,這裡直接set給proxyFactory,定義切點,和切面處理。
再接著走,到了customizeProxyFactory(proxyFactory);這一步其實可以重寫,然後proxyFactory自定義一些需要的屬性等。@Async中沒有重寫,所以這一步我們跳過。
最後到了程式碼*return *proxyFactory.getProxy(getProxyClassLoader());這一步,是不是aop生成代理了。
源碼梳理
所以總結我們上面所有的內容,我們再來梳理一下proxyFactory的偽程式碼過程:
ProxyFactory proxyFactory = new ProxyFactory(); // 目標代理類 proxyFactory.setTarget("UserServiceImpl bean"); // 代理介面 proxyFactory.addInterface("UserService"); // 切點 AsyncAnnotationAdvisor.pointcut = @Async註解 // 環繞通知處理 AsyncAnnotationAdvisor.advice = AnnotationAsyncExecutionInterceptor攔截器 // 切面 = 切點+通知 proxyFactory.addAdvisor("AsyncAnnotationAdvisor"); // 生成代理 UserService userService = proxyFactory.getProxy(getProxyClassLoader());
結合我們第二篇文章中的aop編碼實現方式,是不是很相似了。所以這時候aop我們已經完全定義好了。
接下來我們回頭來看環繞通知處理裡面的業務邏輯,因為現在aop已經生成,攔截@Async之後我們需要非同步處理代理的方法。這時候我們進入AnnotationAsyncExecutionInterceptor的invoke方法。
- 在父類中AsyncExecutionInterceptor#invoke
public Object invoke(final MethodInvocation invocation) throws Throwable { Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null); Method specificMethod = ClassUtils.getMostSpecificMethod(invocation.getMethod(), targetClass); final Method userDeclaredMethod = BridgeMethodResolver.findBridgedMethod(specificMethod); // 獲取executor執行器 AsyncTaskExecutor executor = determineAsyncExecutor(userDeclaredMethod); if (executor == null) { throw new IllegalStateException( "No executor specified and no default executor set on AsyncExecutionInterceptor either"); } // 定義一個Callable非同步執行緒 Callable<Object> task = () -> { try { // 被攔截的方法執行 Object result = invocation.proceed(); if (result instanceof Future) { return ((Future<?>) result).get(); } } catch (ExecutionException ex) { handleError(ex.getCause(), userDeclaredMethod, invocation.getArguments()); } catch (Throwable ex) { handleError(ex, userDeclaredMethod, invocation.getArguments()); } return null; }; return doSubmit(task, executor, invocation.getMethod().getReturnType()); }
上面第一步獲取到executor,然後再通過Callable定義一個非同步執行緒。然後把task放在doSubmit中執行。
protected Object doSubmit(Callable<Object> task, AsyncTaskExecutor executor, Class<?> returnType) { if (CompletableFuture.class.isAssignableFrom(returnType)) { return CompletableFuture.supplyAsync(() -> { try { return task.call(); } catch (Throwable ex) { throw new CompletionException(ex); } }, executor); } else if (ListenableFuture.class.isAssignableFrom(returnType)) { return ((AsyncListenableTaskExecutor) executor).submitListenable(task); } else if (Future.class.isAssignableFrom(returnType)) { return executor.submit(task); } else { executor.submit(task); return null; } }
這裡面就明顯了,就是去執行我們的task,然後返回結果。具體的我們就不再去深究啦。相信到了這一步,我們已經明白了@Async的原理。
以上就是@Async的源碼分析,相對來說還是比較簡單,看過aop源碼的人再來看@Async的話幾乎都不用花什麼時間,所以技術這東西我們要學會多積累。