異步任務spring @Async註解源碼解析

1.引子

開啓異步任務使用方法:

1).方法上加@Async註解 

2).啓動類或者配置類上@EnableAsync

回到頂部

2.源碼解析

雖然spring5已經出來了,但是我們還是使用的spring4,本文就根據spring-context-4.3.14.RELEASE.jar來分析源碼。

2.1.@Async

org.springframework.scheduling.annotation.Async 源碼註釋翻譯:

 1 /**
 2  * Annotation that marks a method as a candidate for <i>asynchronous</i> execution.
 3  * Can also be used at the type level, in which case all of the type's methods are
 4  * considered as asynchronous.該註解可以標記一個異步執行的方法,也可以用來標註類,表示類中的所有方法都是異步執行的。
 5  *
 6  * <p>In terms of target method signatures, any parameter types are supported.
 7  * However, the return type is constrained to either {@code void} or
 8  * {@link java.util.concurrent.Future}. In the latter case, you may declare the
 9  * more specific {@link org.springframework.util.concurrent.ListenableFuture} or
10  * {@link java.util.concurrent.CompletableFuture} types which allow for richer
11  * interaction with the asynchronous task and for immediate composition with
12  * further processing steps.入參隨意,但返回值只能是void或者Future.(ListenableFuture接口/CompletableFuture類)
13  *
14  * <p>A {@code Future} handle returned from the proxy will be an actual asynchronous
15  * {@code Future} that can be used to track the result of the asynchronous method
16  * execution. However, since the target method needs to implement the same signature,
17  * it will have to return a temporary {@code Future} handle that just passes a value
18  * through: e.g. Spring's {@link AsyncResult}, EJB 3.1's {@link javax.ejb.AsyncResult},
19  * or {@link java.util.concurrent.CompletableFuture#completedFuture(Object)}.
20  * Future是代理返回的切實的異步返回,用以追蹤異步方法的返回值。當然也可以使用AsyncResult類(實現ListenableFuture接口)(Spring或者EJB都有)或者CompletableFuture類
21  * @author Juergen Hoeller
22  * @author Chris Beams
23  * @since 3.0
24  * @see AnnotationAsyncExecutionInterceptor
25  * @see AsyncAnnotationAdvisor
26  */
27 @Target({ElementType.METHOD, ElementType.TYPE})
28 @Retention(RetentionPolicy.RUNTIME)
29 @Documented
30 public @interface Async {
31 
32     /**
33      * A qualifier value for the specified asynchronous operation(s).
34      * <p>May be used to determine the target executor to be used when executing this
35      * method, matching the qualifier value (or the bean name) of a specific
36      * {@link java.util.concurrent.Executor Executor} or
37      * {@link org.springframework.core.task.TaskExecutor TaskExecutor}
38      * bean definition.用以限定執行方法的執行器名稱(自定義):Executor或者TaskExecutor
39      * <p>When specified on a class level {@code @Async} annotation, indicates that the
40      * given executor should be used for all methods within the class. Method level use
41      * of {@code Async#value} always overrides any value set at the class level.
42      * @since 3.1.2   加在類上表示整個類都使用,加在方法上會覆蓋類上的設置
43      */
44     String value() default "";
45 
46 }

 

上圖源碼註釋已經寫的很清晰了哈,主要注意3點:

1)返回值:不要返回值直接void;需要返回值用AsyncResult或者CompletableFuture

2)可自定義執行器並指定例如:@Async("otherExecutor")

3)@Async  必須不同類間調用: A類--》B類.C方法()(@Async註釋在B類/方法中),如果在同一個類中調用,會變同步執行,例如:A類.B()-->A類.@Async C(),原因是:底層實現是代理對註解掃描實現的,B方法上沒有註解,沒有生成相應的代理類。(當然把@Async加到類上也能解決但所有方法都異步了,一般不這麼用!)

2.2 @EnableAsync

老規矩咱們直接看類註釋:

//開啓spring異步執行器,類似xml中的task標籤配置,需要聯合@Configuration註解一起使用
Enables Spring's asynchronous method execution capability, similar to functionality found in Spring's <task:*> XML namespace.
To be used together with @Configuration classes as follows, enabling annotation-driven async processing for an entire Spring application context:
 @Configuration
 @EnableAsync
 public class AppConfig {

 }
MyAsyncBean is a user-defined type with one or more methods annotated with either Spring's @Async annotation, the EJB 3.1 @javax.ejb.Asynchronous annotation, or any custom annotation specified via the annotation() attribute. The aspect is added transparently for any registered bean, for instance via this configuration:
 @Configuration
 public class AnotherAppConfig {

     @Bean
     public MyAsyncBean asyncBean() {
         return new MyAsyncBean();
     }
 }

//默認情況下spring會先搜索TaskExecutor類型的bean或者名字爲taskExecutor的Executor類型的bean,都不存在使用SimpleAsyncTaskExecutor執行器
By default, Spring will be searching for an associated thread pool definition: either a unique TaskExecutor bean in the context, or an Executor bean named "taskExecutor" otherwise. If neither of the two is resolvable, a SimpleAsyncTaskExecutor will be used to process async method invocations. Besides, annotated methods having a void return type cannot transmit any exception back to the caller. By default, such uncaught exceptions are only logged.
To customize all this, implement AsyncConfigurer and provide:
your own Executor through the getAsyncExecutor() method, and your own AsyncUncaughtExceptionHandler through the getAsyncUncaughtExceptionHandler() method.//可實現AsyncConfigurer接口複寫getAsyncExecutor獲取異步執行器,getAsyncUncaughtExceptionHandler獲取異步未捕獲異常處理器
 @Configuration
 @EnableAsync
 public class AppConfig implements AsyncConfigurer {

     @Override
     public Executor getAsyncExecutor() {
         ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
         executor.setCorePoolSize(7);
         executor.setMaxPoolSize(42);
         executor.setQueueCapacity(11);
         executor.setThreadNamePrefix("MyExecutor-");
         executor.initialize();
         return executor;
     }

     @Override
     public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
         return MyAsyncUncaughtExceptionHandler();
     }
 }
If only one item needs to be customized, null can be returned to keep the default settings. Consider also extending from AsyncConfigurerSupport when possible.
Note: In the above example the ThreadPoolTaskExecutor is not a fully managed Spring bean. Add the @Bean annotation to the getAsyncExecutor() method if you want a fully managed bean. In such circumstances it is no longer necessary to manually call the executor.initialize() method as this will be invoked automatically when the bean is initialized.
For reference, the example above can be compared to the following Spring XML configuration:
 <beans>

     <task:annotation-driven executor="myExecutor" exception-handler="exceptionHandler"/>

     <task:executor id="myExecutor" pool-size="7-42" queue-capacity="11"/>

     <bean id="asyncBean" class="com.foo.MyAsyncBean"/>

     <bean id="exceptionHandler" class="com.foo.MyAsyncUncaughtExceptionHandler"/>

 </beans>
 //註解類和xml基本一致,但是使用註解類還可以自定義線程名前綴(上面的AppConfig-》getAsyncExecutor-》setThreadNamePrefix)
The above XML-based and JavaConfig-based examples are equivalent except for the setting of the thread name prefix of the Executor; this is because the <task:executor> element does not expose such an attribute. This demonstrates how the JavaConfig-based approach allows for maximum configurability through direct access to actual componentry.
The mode() attribute controls how advice is applied: If the mode is AdviceMode.PROXY (the default), then the other attributes control the behavior of the proxying. Please note that proxy mode allows for interception of calls through the proxy only; local calls within the same class cannot get intercepted that way.//這裏就說明了@Async必須在不同方法中調用,即第一部分注意的第三點。
Note that if the mode() is set to AdviceMode.ASPECTJ, then the value of the proxyTargetClass() attribute will be ignored. Note also that in this case the spring-aspects module JAR must be present on the classpath, with compile-time weaving or load-time weaving applying the aspect to the affected classes. There is no proxy involved in such a scenario; local calls will be intercepted as well.//當然也可以用Aspect模式織入(需要引入spring-aspects模塊需要的jar)
 

下面是源碼:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AsyncConfigurationSelector.class)
public @interface EnableAsync {

   /**該屬性用來支持用戶自定義異步註解,默認掃描spring的@Async和EJB3.1的@code @javax.ejb.Asynchronous
    * Indicate the 'async' annotation type to be detected at either class
    * or method level.
    * <p>By default, both Spring's @{@link Async} annotation and the EJB 3.1
    * {@code @javax.ejb.Asynchronous} annotation will be detected.
    * <p>This attribute exists so that developers can provide their own
    * custom annotation type to indicate that a method (or all methods of
    * a given class) should be invoked asynchronously.
    */
   Class<? extends Annotation> annotation() default Annotation.class;

   /**標明是否需要創建CGLIB子類代理,AdviceMode=PROXY時才適用。注意設置爲true時,其它spring管理的bean也會升級到CGLIB子類代理
    * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
    * to standard Java interface-based proxies.
    * <p><strong>Applicable only if the {@link #mode} is set to {@link AdviceMode#PROXY}</strong>.
    * <p>The default is {@code false}.
    * <p>Note that setting this attribute to {@code true} will affect <em>all</em>
    * Spring-managed beans requiring proxying, not just those marked with {@code @Async}.
    * For example, other beans marked with Spring's {@code @Transactional} annotation
    * will be upgraded to subclass proxying at the same time. This approach has no
    * negative impact in practice unless one is explicitly expecting one type of proxy
    * vs. another &mdash; for example, in tests.
    */
   boolean proxyTargetClass() default false;

   /**標明異步通知將會如何實現,默認PROXY,如需支持同一個類中非異步方法調用另一個異步方法,需要設置爲ASPECTJ
    * Indicate how async advice should be applied.
    * <p><b>The default is {@link AdviceMode#PROXY}.</b>
    * Please note that proxy mode allows for interception of calls through the proxy
    * only. Local calls within the same class cannot get intercepted that way; an
    * {@link Async} annotation on such a method within a local call will be ignored
    * since Spring's interceptor does not even kick in for such a runtime scenario.
    * For a more advanced mode of interception, consider switching this to
    * {@link AdviceMode#ASPECTJ}.
    */
   AdviceMode mode() default AdviceMode.PROXY;

   /**標明異步註解bean處理器應該遵循的執行順序,默認最低的優先級(Integer.MAX_VALUE,值越小優先級越高)
    * Indicate the order in which the {@link AsyncAnnotationBeanPostProcessor}
    * should be applied.
    * <p>The default is {@link Ordered#LOWEST_PRECEDENCE} in order to run
    * after all other post-processors, so that it can add an advisor to
    * existing proxies rather than double-proxy.
    */
   int order() default Ordered.LOWEST_PRECEDENCE;

}

執行流程:

如上圖,核心註解就是@Import(AsyncConfigurationSelector.class),一看就是套路ImportSelector接口的selectImports()方法,源碼如下:

 1 /**查詢器:基於@EanableAsync中定義的模式AdviceMode加在@Configuration標記的類上,確定抽象異步配置類的實現類
 2  * Selects which implementation of {@link AbstractAsyncConfiguration} should be used based
 3  * on the value of {@link EnableAsync#mode} on the importing {@code @Configuration} class.
 4  *
 5  * @author Chris Beams
 6  * @since 3.1
 7  * @see EnableAsync
 8  * @see ProxyAsyncConfiguration
 9  */
10 public class AsyncConfigurationSelector extends AdviceModeImportSelector<EnableAsync> {
11 
12     private static final String ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME =
13             "org.springframework.scheduling.aspectj.AspectJAsyncConfiguration";
14 
15     /**
16      * {@inheritDoc}
17      * @return {@link ProxyAsyncConfiguration} or {@code AspectJAsyncConfiguration} for
18      * {@code PROXY} and {@code ASPECTJ} values of {@link EnableAsync#mode()}, respectively
19      */
20     @Override
21     public String[] selectImports(AdviceMode adviceMode) {
22         switch (adviceMode) {
23             case PROXY://如果配置的PROXY,使用ProxyAsyncConfiguration
24                 return new String[] { ProxyAsyncConfiguration.class.getName() };
25             case ASPECTJ://如果配置的ASPECTJ,使用ProxyAsyncConfiguration
26                 return new String[] { ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME };
27             default:
28                 return null;
29         }
30     }
31 
32 }

 

我們就選一個類ProxyAsyncConfiguration(JDK接口代理)看一下具體實現:

 1 /**
 2  * {@code @Configuration} class that registers the Spring infrastructure beans necessary
 3  * to enable proxy-based asynchronous method execution.
 4  *
 5  * @author Chris Beams
 6  * @author Stephane Nicoll
 7  * @since 3.1
 8  * @see EnableAsync
 9  * @see AsyncConfigurationSelector
10  */
11 @Configuration
12 @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
13 public class ProxyAsyncConfiguration extends AbstractAsyncConfiguration {
14 
15     @Bean(name = TaskManagementConfigUtils.ASYNC_ANNOTATION_PROCESSOR_BEAN_NAME)
16     @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
17     public AsyncAnnotationBeanPostProcessor asyncAdvisor() {
18         Assert.notNull(this.enableAsync, "@EnableAsync annotation metadata was not injected");
19         AsyncAnnotationBeanPostProcessor bpp = new AsyncAnnotationBeanPostProcessor();//新建一個異步註解bean後處理器
20         Class<? extends Annotation> customAsyncAnnotation = this.enableAsync.getClass("annotation");
21         //如果@EnableAsync中用戶自定義了annotation屬性,即異步註解類型,那麼設置           
       if (customAsyncAnnotation != AnnotationUtils.getDefaultValue(EnableAsync.class, "annotation")) {
22             bpp.setAsyncAnnotationType(customAsyncAnnotation);
23         }
24         if (this.executor != null) {//Executor:設置線程任務執行器
25             bpp.setExecutor(this.executor);
26         }
27         if (this.exceptionHandler != null) {//AsyncUncaughtExceptionHandler:設置異常處理器
28             bpp.setExceptionHandler(this.exceptionHandler);
29         }
30         bpp.setProxyTargetClass(this.enableAsync.getBoolean("proxyTargetClass"));//設置是否升級到CGLIB子類代理,默認不開啓
31         bpp.setOrder(this.enableAsync.<Integer>getNumber("order"));//設置執行優先級,默認最後執行
32         return bpp;
33     }
34 
35 }

 

如上圖,ProxyAsyncConfiguration就兩點:

1.就是繼承了AbstractAsyncConfiguration類

2.定義了一個bean:AsyncAnnotationBeanPostProcessor

2.AbstractAsyncConfiguration源碼:

 1 /**
 2  * Abstract base {@code Configuration} class providing common structure for enabling
 3  * Spring's asynchronous method execution capability.
 4  * 抽象異步配置類,封裝了通用結構,用以支持spring的異步方法執行能力
 5  * @author Chris Beams
 6  * @author Stephane Nicoll
 7  * @since 3.1
 8  * @see EnableAsync
 9  */
10 @Configuration
11 public abstract class AbstractAsyncConfiguration implements ImportAware {
12 
13     protected AnnotationAttributes enableAsync;//enableAsync的註解屬性
14 
15     protected Executor executor;//Doug Lea老李頭設計的線程任務執行器
16 
17     protected AsyncUncaughtExceptionHandler exceptionHandler;//異常處理器
18 
19 
20     @Override
21     public void setImportMetadata(AnnotationMetadata importMetadata) {
22         this.enableAsync = AnnotationAttributes.fromMap(
23                 importMetadata.getAnnotationAttributes(EnableAsync.class.getName(), false));
24         if (this.enableAsync == null) {
25             throw new IllegalArgumentException(
26                     "@EnableAsync is not present on importing class " + importMetadata.getClassName());
27         }
28     }
29 
30     /**
31      * Collect any {@link AsyncConfigurer} beans through autowiring.
32      */
33     @Autowired(required = false)
34     void setConfigurers(Collection<AsyncConfigurer> configurers) {
35         if (CollectionUtils.isEmpty(configurers)) {
36             return;
37         }
38         if (configurers.size() > 1) {
39             throw new IllegalStateException("Only one AsyncConfigurer may exist");
40         }
41         AsyncConfigurer configurer = configurers.iterator().next();
42         this.executor = configurer.getAsyncExecutor();
43         this.exceptionHandler = configurer.getAsyncUncaughtExceptionHandler();
44     }
45 
46 }

 

很清晰哈,

屬性:

1)註解屬性

2)異步任務執行器

3)異常處理器

方法:

1)setImportMetadata 設置註解屬性,即屬性1

2)setConfigurers 設置異步任務執行器和異常處理器,即屬性2,3

2.AsyncAnnotationBeanPostProcessor這個Bean,類圖如下:

後面詳細分析AOP詳細過程。

2.3.AOP-Advisor切面初始化:(AsyncAnnotationBeanPostProcessor -》setBeanFactory())

AsyncAnnotationBeanPostProcessor這個類的Bean 初始化時 : BeanFactoryAware接口setBeanFactory方法中,對AsyncAnnotationAdvisor異步註解切面進行了構造。

 1 @Override
 2     public void setBeanFactory(BeanFactory beanFactory) {
 3         super.setBeanFactory(beanFactory);
 4 
 5         AsyncAnnotationAdvisor advisor = new AsyncAnnotationAdvisor(this.executor, this.exceptionHandler);
 6         if (this.asyncAnnotationType != null) {
 7             advisor.setAsyncAnnotationType(this.asyncAnnotationType);
 8         }
 9         advisor.setBeanFactory(beanFactory);
10         this.advisor = advisor;
11     }

AsyncAnnotationAdvisor的類圖如下:

2.4.AOP-生成代理類AopProxy(AsyncAnnotationBeanPostProcessor -》postProcessAfterInitialization())

具體的後置處理:AsyncAnnotationBeanPostProcessor的後置bean處理是通過其父類AbstractAdvisingBeanPostProcessor來實現的,

該類實現了BeanPostProcessor接口,複寫postProcessAfterInitialization方法如下圖所示:

 1 @Override
 2     public Object postProcessAfterInitialization(Object bean, String beanName) {
 3         if (bean instanceof AopInfrastructureBean) {
 4             // Ignore AOP infrastructure such as scoped proxies.
 5             return bean;
 6         }
 7         //把Advisor添加進bean  ProxyFactory-》AdvisedSupport-》Advised
 8         if (bean instanceof Advised) {
 9             Advised advised = (Advised) bean;
10             if (!advised.isFrozen() && isEligible(AopUtils.getTargetClass(bean))) {
11                 // Add our local Advisor to the existing proxy's Advisor chain...
12                 if (this.beforeExistingAdvisors) {
13                     advised.addAdvisor(0, this.advisor);
14                 }
15                 else {
16                     advised.addAdvisor(this.advisor);
17                 }
18                 return bean;
19             }
20         }
21         //構造ProxyFactory代理工廠,添加代理的接口,設置切面,最後返回代理類:AopProxy
22         if (isEligible(bean, beanName)) {
23             ProxyFactory proxyFactory = prepareProxyFactory(bean, beanName);
24             if (!proxyFactory.isProxyTargetClass()) {
25                 evaluateProxyInterfaces(bean.getClass(), proxyFactory);
26             }
27             proxyFactory.addAdvisor(this.advisor);
28             customizeProxyFactory(proxyFactory);
29             return proxyFactory.getProxy(getProxyClassLoader());
30         }
31 
32         // No async proxy needed.
33         return bean;
34     }

isEligible用於判斷這個類或者這個類中的某個方法是否含有註解,AsyncAnnotationAdvisor 實現了PointcutAdvisor接口,滿足條件2如下圖:

19   public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
20         if (advisor instanceof IntroductionAdvisor) {
21             return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
22         }//滿足第二分支PointcutAdvisor
23         else if (advisor instanceof PointcutAdvisor) {
24             PointcutAdvisor pca = (PointcutAdvisor) advisor;
25             return canApply(pca.getPointcut(), targetClass, hasIntroductions);
26         }
27         else {
28             // It doesn't have a pointcut so we assume it applies.
29             return true;
30         }
31     }

isEligible校驗通過後,構造ProxyFactory代理工廠,添加代理的接口,設置切面,最後返回代理類:AopProxy接口實現類

2.5.AOP-切點執行(InvocationHandler.invoke)

上一步生成的代理AopProxy接口,我們這裏最終實際生成的是JdkDynamicAopProxy,即JDK動態代理類,類圖如下:

最終執行的是InvocationHandler接口的invoke方法,下面是截取出來的核心代碼:

 1 // 得到方法的攔截器鏈
 2 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
 3 // Check whether we have any advice. If we don't, we can fallback on direct
 4 // reflective invocation of the target, and avoid creating a MethodInvocation.
 5 if (chain.isEmpty()) {
 6     // We can skip creating a MethodInvocation: just invoke the target directly
 7     // Note that the final invoker must be an InvokerInterceptor so we know it does
 8     // nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
 9     Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
10     retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
11 }
12 else {
13     // 構造
14     invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
15     // Proceed to the joinpoint through the interceptor chain.
16     retVal = invocation.proceed();
17 }

@Async註解的攔截器是AsyncExecutionInterceptor,它繼承了MethodInterceptor接口。而MethodInterceptor就是AOP規範中的Advice(切點的處理器)。

chain不爲空,執行第二個分支,構造ReflectiveMethodInvocation,然後執行proceed方法。

 1 @Override
 2     public Object proceed() throws Throwable {
 3         //    如果沒有攔截器,直接執行被代理的方法
 4         if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
 5             return invokeJoinpoint();
 6         }
 7 
 8         Object interceptorOrInterceptionAdvice =
 9                 this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
10         if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
11             // Evaluate dynamic method matcher here: static part will already have
12             // been evaluated and found to match.
13             InterceptorAndDynamicMethodMatcher dm =
14                     (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
15             if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
16                 return dm.interceptor.invoke(this);
17             }
18             else {
19                 // Dynamic matching failed.
20                 // Skip this interceptor and invoke the next in the chain.
21                 return proceed();
22             }
23         }
24         else {
25             // It's an interceptor, so we just invoke it: The pointcut will have
26             // been evaluated statically before this object was constructed.
27             return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
28         }
29     }

如上圖,核心方法是InterceptorAndDynamicMethodMatcher.interceptor.invoke(this),實際就是執行了AsyncExecutionInterceptor.invoke,繼續追!

 

 1 public Object invoke(final MethodInvocation invocation) throws Throwable {
 2         Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
 3         Method specificMethod = ClassUtils.getMostSpecificMethod(invocation.getMethod(), targetClass);
 4         final Method userDeclaredMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
 5 
 6         AsyncTaskExecutor executor = determineAsyncExecutor(userDeclaredMethod);
 7         if (executor == null) {
 8             throw new IllegalStateException(//如果沒有自定義異步任務執行器,報下面這行錯,不用管,可以默認執行
 9                     "No executor specified and no default executor set on AsyncExecutionInterceptor either");
10         }
11 
12         Callable<Object> task = new Callable<Object>() {
13             @Override
14             public Object call() throws Exception {
15                 try {
16                     Object result = invocation.proceed();
17                     if (result instanceof Future) {
18                         return ((Future<?>) result).get();//阻塞等待執行完畢得到結果
19                     }
20                 }
21                 catch (ExecutionException ex) {
22                     handleError(ex.getCause(), userDeclaredMethod, invocation.getArguments());
23                 }
24                 catch (Throwable ex) {
25                     handleError(ex, userDeclaredMethod, invocation.getArguments());
26                 }
27                 return null;
28             }
29         };
30         //提交有任務給執行器
31         return doSubmit(task, executor, invocation.getMethod().getReturnType());
32     }

 終極執行核心方法doSubmit()

 1 protected Object doSubmit(Callable<Object> task, AsyncTaskExecutor executor, Class<?> returnType) {
 2         if (completableFuturePresent) {//先判斷是否存在CompletableFuture這個類,優先使用CompletableFuture執行任務
 3             Future<Object> result = CompletableFutureDelegate.processCompletableFuture(returnType, task, executor);
 4             if (result != null) {
 5                 return result;
 6             }
 7         }//返回值是可監聽Future,定義過回調函數:addCallback
 8         if (ListenableFuture.class.isAssignableFrom(returnType)) {
 9             return ((AsyncListenableTaskExecutor) executor).submitListenable(task);
10         }//返回值是Future
11         else if (Future.class.isAssignableFrom(returnType)) {
12             return executor.submit(task);
13         }
14         else {//沒有返回值
15             executor.submit(task);
16             return null;
17         }
18     }

 最終執行:就是開啓一個線程啓動...

1 protected void doExecute(Runnable task) {
2         Thread thread = (this.threadFactory != null ? this.threadFactory.newThread(task) : createThread(task));
3         thread.start();
4     }

回到頂部

3.總結

整體流程大體可梳理爲兩條線:

1.從註解開始:@EnableAsync--》ProxyAsyncConfiguration類構造一個bean(類型:AsyncAnnotationBeanPostProcessor)

2.從AsyncAnnotationBeanPostProcessor這個類的bean的生命週期走:AOP-Advisor切面初始化(setBeanFactory())--》AOP-生成代理類AopProxy(postProcessAfterInitialization())--》AOP-切點執行(InvocationHandler.invoke)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章