日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 前端技术 > javascript >内容正文

javascript

【转载】Spring @Async 源码解读。

發(fā)布時(shí)間:2024/4/17 javascript 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【转载】Spring @Async 源码解读。 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

由于工作中經(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é)
  • 2.1.@Async
  • 2.2 @EnableAsync
  • 2.3.AOP-Advisor切面初始化:(AsyncAnnotationBeanPostProcessor -》setBeanFactory())
  • 2.4.AOP-生成代理類(lèi)AopProxy(AsyncAnnotationBeanPostProcessor -》postProcessAfterInitialization())
  • 2.5.AOP-切點(diǎn)執(zhí)行(InvocationHandler.invoke)
  • ?

    正文

    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 //開(kāi)啟spring異步執(zhí)行器,類(lèi)似xml中的task標(biāo)簽配置,需要聯(lián)合@Configuration注解一起使用 2 Enables Spring's asynchronous method execution capability, similar to functionality found in Spring's <task:*> XML namespace. 3 To be used together with @Configuration classes as follows, enabling annotation-driven async processing for an entire Spring application context: 4 @Configuration 5 @EnableAsync 6 public class AppConfig { 7 8 } 9 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: 10 @Configuration 11 public class AnotherAppConfig { 12 13 @Bean 14 public MyAsyncBean asyncBean() { 15 return new MyAsyncBean(); 16 } 17 } 18 19 //默認(rèn)情況下spring會(huì)先搜索TaskExecutor類(lèi)型的bean或者名字為taskExecutor的Executor類(lèi)型的bean,都不存在使用SimpleAsyncTaskExecutor執(zhí)行器 20 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. 21 To customize all this, implement AsyncConfigurer and provide: 22 your own Executor through the getAsyncExecutor() method, and your own AsyncUncaughtExceptionHandler through the getAsyncUncaughtExceptionHandler() method.//可實(shí)現(xiàn)AsyncConfigurer接口復(fù)寫(xiě)getAsyncExecutor獲取異步執(zhí)行器,getAsyncUncaughtExceptionHandler獲取異步未捕獲異常處理器 23 @Configuration 24 @EnableAsync 25 public class AppConfig implements AsyncConfigurer { 26 27 @Override 28 public Executor getAsyncExecutor() { 29 ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); 30 executor.setCorePoolSize(7); 31 executor.setMaxPoolSize(42); 32 executor.setQueueCapacity(11); 33 executor.setThreadNamePrefix("MyExecutor-"); 34 executor.initialize(); 35 return executor; 36 } 37 38 @Override 39 public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { 40 return MyAsyncUncaughtExceptionHandler(); 41 } 42 }

    ?

    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 &mdash; 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)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。