javascript
【转载】Spring @Async 源码解读。
由于工作中經(jīng)常需要使用到異步操作,一直在使用@Async, 今天抽空學(xué)習(xí)了一下它的執(zhí)行原理,剛好看到一篇寫(xiě)的很棒的文章,這里轉(zhuǎn)載過(guò)來(lái)做個(gè)記錄,感謝原作者的無(wú)私奉獻(xiàn)。
原文章鏈接地址:https://www.cnblogs.com/dennyzhangdd/p/9026303.html#_label1_4
目錄
- 1.引子
- 2.源碼解析3.總結(jié)
?
正文
1.引子
開(kāi)啟異步任務(wù)使用方法:
1).方法上加@Async注解
2).啟動(dòng)類(lèi)或者配置類(lèi)上@EnableAsync
2.源碼解析
雖然spring5已經(jīng)出來(lái)了,但是我們還是使用的spring4,本文就根據(jù)spring-context-4.3.14.RELEASE.jar來(lái)分析源碼。
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.該注解可以標(biāo)記一個(gè)異步執(zhí)行的方法,也可以用來(lái)標(biāo)注類(lèi),表示類(lèi)中的所有方法都是異步執(zhí)行的。 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.入?yún)㈦S意,但返回值只能是void或者Future.(ListenableFuture接口/CompletableFuture類(lèi))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是代理返回的切實(shí)的異步返回,用以追蹤異步方法的返回值。當(dāng)然也可以使用AsyncResult類(lèi)(實(shí)現(xiàn)ListenableFuture接口)(Spring或者EJB都有)或者CompletableFuture類(lèi) 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.用以限定執(zhí)行方法的執(zhí)行器名稱(chēng)(自定義):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 加在類(lèi)上表示整個(gè)類(lèi)都使用,加在方法上會(huì)覆蓋類(lèi)上的設(shè)置 43 */ 44 String value() default ""; 45 46 }
上圖源碼注釋已經(jīng)寫(xiě)的很清晰了哈,主要注意3點(diǎn):
1)返回值:不要返回值直接void;需要返回值用AsyncResult或者CompletableFuture
2)可自定義執(zhí)行器并指定例如:@Async("otherExecutor")
3)@Async? 必須不同類(lèi)間調(diào)用: A類(lèi)--》B類(lèi).C方法()(@Async注釋在B類(lèi)/方法中),如果在同一個(gè)類(lèi)中調(diào)用,會(huì)變同步執(zhí)行,例如:A類(lèi).B()-->A類(lèi).@Async C(),原因是:底層實(shí)現(xiàn)是代理對(duì)注解掃描實(shí)現(xiàn)的,B方法上沒(méi)有注解,沒(méi)有生成相應(yīng)的代理類(lèi)。(當(dāng)然把@Async加到類(lèi)上也能解決但所有方法都異步了,一般不這么用!)
2.2?@EnableAsync
老規(guī)矩咱們直接看類(lèi)注釋:
?
1 If only one item needs to be customized, null can be returned to keep the default settings. Consider also extending from AsyncConfigurerSupport when possible. 2 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. 3 For reference, the example above can be compared to the following Spring XML configuration: 4 <beans> 5 6 <task:annotation-driven executor="myExecutor" exception-handler="exceptionHandler"/> 7 8 <task:executor id="myExecutor" pool-size="7-42" queue-capacity="11"/> 9 10 <bean id="asyncBean" class="com.foo.MyAsyncBean"/> 11 12 <bean id="exceptionHandler" class="com.foo.MyAsyncUncaughtExceptionHandler"/> 13 14 </beans> 15 //注解類(lèi)和xml基本一致,但是使用注解類(lèi)還可以自定義線程名前綴(上面的AppConfig-》getAsyncExecutor-》setThreadNamePrefix) 16 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. 17 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.//這里就說(shuō)明了@Async必須在不同方法中調(diào)用,即第一部分注意的第三點(diǎn)。 18 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.//當(dāng)然也可以用Aspect模式織入(需要引入spring-aspects模塊需要的jar)?
?
下面是源碼:
@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AsyncConfigurationSelector.class)
public @interface ? {
/**該屬性用來(lái)支持用戶(hù)自定義異步注解,默認(rèn)掃描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;
/**標(biāo)明是否需要?jiǎng)?chuàng)建CGLIB子類(lèi)代理,AdviceMode=PROXY時(shí)才適用。注意設(shè)置為true時(shí),其它spring管理的bean也會(huì)升級(jí)到CGLIB子類(lèi)代理
* 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 — for example, in tests.
*/
boolean proxyTargetClass() default false;
/**標(biāo)明異步通知將會(huì)如何實(shí)現(xiàn),默認(rèn)PROXY,如需支持同一個(gè)類(lèi)中非異步方法調(diào)用另一個(gè)異步方法,需要設(shè)置為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;
/**標(biāo)明異步注解bean處理器應(yīng)該遵循的執(zhí)行順序,默認(rèn)最低的優(yōu)先級(jí)(Integer.MAX_VALUE,值越小優(yōu)先級(jí)越高)
* 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;
}
執(zhí)行流程:
如上圖,核心注解就是@Import(AsyncConfigurationSelector.class),一看就是套路ImportSelector接口的selectImports()方法,源碼如下:
1 /**查詢(xún)器:基于@EanableAsync中定義的模式AdviceMode加在@Configuration標(biāo)記的類(lèi)上,確定抽象異步配置類(lèi)的實(shí)現(xiàn)類(lèi) 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 }?
我們就選一個(gè)類(lèi)ProxyAsyncConfiguration(JDK接口代理)看一下具體實(shí)現(xiàn):
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();//新建一個(gè)異步注解bean后處理器 20 Class<? extends Annotation> customAsyncAnnotation = this.enableAsync.getClass("annotation"); 21 //如果@EnableAsync中用戶(hù)自定義了annotation屬性,即異步注解類(lèi)型,那么設(shè)置if (customAsyncAnnotation != AnnotationUtils.getDefaultValue(EnableAsync.class, "annotation")) { 22 bpp.setAsyncAnnotationType(customAsyncAnnotation); 23 } 24 if (this.executor != null) {//Executor:設(shè)置線程任務(wù)執(zhí)行器 25 bpp.setExecutor(this.executor); 26 } 27 if (this.exceptionHandler != null) {//AsyncUncaughtExceptionHandler:設(shè)置異常處理器 28 bpp.setExceptionHandler(this.exceptionHandler); 29 } 30 bpp.setProxyTargetClass(this.enableAsync.getBoolean("proxyTargetClass"));//設(shè)置是否升級(jí)到CGLIB子類(lèi)代理,默認(rèn)不開(kāi)啟 31 bpp.setOrder(this.enableAsync.<Integer>getNumber("order"));//設(shè)置執(zhí)行優(yōu)先級(jí),默認(rèn)最后執(zhí)行 32 return bpp; 33 } 34 35 }
如上圖,ProxyAsyncConfiguration就兩點(diǎn):
1.就是繼承了AbstractAsyncConfiguration類(lèi)
2.定義了一個(gè)bean:AsyncAnnotationBeanPostProcessor
2.AbstractAsyncConfiguration源碼:
1 /**2 * Abstract base {@code Configuration} class providing common structure for enabling3 * Spring's asynchronous method execution capability.4 * 抽象異步配置類(lèi),封裝了通用結(jié)構(gòu),用以支持spring的異步方法執(zhí)行能力5 * @author Chris Beams6 * @author Stephane Nicoll7 * @since 3.18 * @see EnableAsync9 */ 10 @Configuration 11 public abstract class AbstractAsyncConfiguration implements ImportAware { 12 13 protected AnnotationAttributes enableAsync;//enableAsync的注解屬性 14 15 protected Executor executor;//Doug Lea老李頭設(shè)計(jì)的線程任務(wù)執(zhí)行器 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)異步任務(wù)執(zhí)行器
3)異常處理器
方法:
1)setImportMetadata 設(shè)置注解屬性,即屬性1
2)setConfigurers 設(shè)置異步任務(wù)執(zhí)行器和異常處理器,即屬性2,3
2.AsyncAnnotationBeanPostProcessor這個(gè)Bean,類(lèi)圖如下:
后面詳細(xì)分析AOP詳細(xì)過(guò)程。
2.3.AOP-Advisor切面初始化:(AsyncAnnotationBeanPostProcessor -》setBeanFactory())
AsyncAnnotationBeanPostProcessor這個(gè)類(lèi)的Bean 初始化時(shí) : BeanFactoryAware接口setBeanFactory方法中,對(duì)AsyncAnnotationAdvisor異步注解切面進(jìn)行了構(gòu)造。
1 @Override2 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的類(lèi)圖如下:
2.4.AOP-生成代理類(lèi)AopProxy(AsyncAnnotationBeanPostProcessor -》postProcessAfterInitialization())
具體的后置處理:AsyncAnnotationBeanPostProcessor的后置bean處理是通過(guò)其父類(lèi)AbstractAdvisingBeanPostProcessor來(lái)實(shí)現(xiàn)的,
該類(lèi)實(shí)現(xiàn)了BeanPostProcessor接口,復(fù)寫(xiě)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添加進(jìn)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 //構(gòu)造ProxyFactory代理工廠,添加代理的接口,設(shè)置切面,最后返回代理類(lèi):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用于判斷這個(gè)類(lèi)或者這個(gè)類(lèi)中的某個(gè)方法是否含有注解,AsyncAnnotationAdvisor?實(shí)現(xiàn)了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校驗(yàn)通過(guò)后,構(gòu)造ProxyFactory代理工廠,添加代理的接口,設(shè)置切面,最后返回代理類(lèi):AopProxy接口實(shí)現(xiàn)類(lèi)
2.5.AOP-切點(diǎn)執(zhí)行(InvocationHandler.invoke)
上一步生成的代理AopProxy接口,我們這里最終實(shí)際生成的是JdkDynamicAopProxy,即JDK動(dòng)態(tài)代理類(lèi),類(lèi)圖如下:
最終執(zhí)行的是InvocationHandler接口的invoke方法,下面是截取出來(lái)的核心代碼:
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 // 構(gòu)造 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規(guī)范中的Advice(切點(diǎn)的處理器)。
chain不為空,執(zhí)行第二個(gè)分支,構(gòu)造ReflectiveMethodInvocation,然后執(zhí)行proceed方法。
1 @Override 2 public Object proceed() throws Throwable { 3 // 如果沒(méi)有攔截器,直接執(zhí)行被代理的方法 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),實(shí)際就是執(zhí)行了AsyncExecutionInterceptor.invoke,繼續(xù)追!
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(//如果沒(méi)有自定義異步任務(wù)執(zhí)行器,報(bào)下面這行錯(cuò),不用管,可以默認(rèn)執(zhí)行 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();//阻塞等待執(zhí)行完畢得到結(jié)果 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 //提交有任務(wù)給執(zhí)行器 31 return doSubmit(task, executor, invocation.getMethod().getReturnType()); 32 }終極執(zhí)行核心方法doSubmit()
1 protected Object doSubmit(Callable<Object> task, AsyncTaskExecutor executor, Class<?> returnType) { 2 if (completableFuturePresent) {//先判斷是否存在CompletableFuture這個(gè)類(lèi),優(yōu)先使用CompletableFuture執(zhí)行任務(wù) 3 Future<Object> result = CompletableFutureDelegate.processCompletableFuture(returnType, task, executor); 4 if (result != null) { 5 return result; 6 } 7 }//返回值是可監(jiān)聽(tīng)Future,定義過(guò)回調(diào)函數(shù):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 {//沒(méi)有返回值 15 executor.submit(task); 16 return null; 17 } 18 }最終執(zhí)行:就是開(kāi)啟一個(gè)線程啟動(dòng)...
1 protected void doExecute(Runnable task) { 2 Thread thread = (this.threadFactory != null ? this.threadFactory.newThread(task) : createThread(task)); 3 thread.start(); 4 } 回到頂部3.總結(jié)
整體流程大體可梳理為兩條線:
1.從注解開(kāi)始:@EnableAsync--》ProxyAsyncConfiguration類(lèi)構(gòu)造一個(gè)bean(類(lèi)型:AsyncAnnotationBeanPostProcessor)
2.從AsyncAnnotationBeanPostProcessor這個(gè)類(lèi)的bean的生命周期走:AOP-Advisor切面初始化(setBeanFactory())--》AOP-生成代理類(lèi)AopProxy(postProcessAfterInitialization())--》AOP-切點(diǎn)執(zhí)行(InvocationHandler.invoke)
轉(zhuǎn)載于:https://www.cnblogs.com/wang-meng/p/9478029.html
總結(jié)
以上是生活随笔為你收集整理的【转载】Spring @Async 源码解读。的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: linux swap交换分区说明/管理
- 下一篇: angularJS 修改操作select