前言@Async通过注解标记实现方法的异步执行;对于注解的底层实现,除了java原生提供的依赖编译期植入外,其他基本相同,即运行时使用反射等方式拦截被注解的类或方法,以及然后在执行过程中进行横切拦截;另外,这里还有一点就是方法是异步执行的,所以对于@Async的分析,必须要有两个基础知识点,就是代理和线程池。了解了这些之后,我们来拆解一下@Async的基本原理。如何激活它?@EnableAsync注释开启了Spring在后台线程池中运行@Async方法的能力。通过@EnableAsync启用异步方法的能力。@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Import(AsyncConfigurationSelector.class)public@interfaceEnableAsync{//...`}复制代码@EnableAsync注解导入AsyncConfigurationSelector,在SpringBoot中很重要A常见的写法,这里需要注意的是选择了哪个自动配置类;adviceMode默认为false,这里是ProxyAsyncConfiguration的一个例子:caseASPECTJ:returnnewString[]{ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME};默认值:返回空值;}}最重要的是创建AsyncAnnotationBeanPostProcessor。从名字上看,AsyncAnnotationBeanPostProcessor就是处理@Async注解;目的很明确,就是创建一个bean对应的代理对象,这样在方法执行的时候就可以进行AOP拦截了(见org.springframework.aop.framework.AbstractAdvisingBeanPostProcessor#postProcessAfterInitialization这个方法)ProxyFactoryproxyFactory=prepareProxyFactory(bean,beanName);如果(!proxyFactory.isProxyTargetClass()){evaluateProxyInterfaces(bean.getClass(),proxyFactory););复制代码编辑AnnotationAsyncExecutionInterceptor这个涉及到AOP的一些基础知识,可以参考之前写的juejin.cn/post/684490...本文AOP的最外层是代理类,然后是weaver(advisor),然后是建议和PointCut;前面已经介绍了创建代理对象的逻辑,那么接下来就是创建顾问和切入点了。其实advisor的创建逻辑也是在AsyncAnnotationBeanPostProcessor中完成的。@OverridepublicvoidsetBeanFactory(BeanFactorybeanFactory){super.setBeanFactory(beanFactory);//创建顾问AsyncAnnotationAdvisoradvisor=newAsyncAnnotationAdvisor(this.executor,this.exceptionHandler);如果(this.asyncAnnotationType!=null){advisorAsyncAnnotation(Typethis.asyncAnnotationType);}advisor.setBeanFactory(beanFactory);this.advisor=顾问;}复制代码在AsyncAnnotationAdvisor的构造函数中,会构造Advice和PointcutpublicAsyncAnnotationAdvisor(@NullableSupplierexecutor,@NullableSupplierexceptionHandler){//省略其他代码///...//创建advicethis.advice=buildAdvice(executor,exceptionHandler);//创建切入点this.pointcut=buildPointcut(asyncAnnotationTypes);}复制代码Advice是具体的执行拦截按照逻辑,这里的advice其实就是AnnotationAsyncExecutionInterceptor(为什么?因为Advice是MethodInterceptor的父类)。protectedAdvicebuildAdvice(@NullableSupplierexecutor,@NullableSupplierexceptionHandler){//这里AnnotationAsyncExecutionInterceptorinterceptor=newAnnotationAsyncExecutionInterceptor(null);拦截器配置(执行器,异常处理程序);返回拦截器;复制代码到这里,基本介绍了@EnableAsync如何开启异步方法创建的逻辑;本质上就是SpringAOP的逻辑。Tips除了adviceMode,一般情况下,还会涉及到另一个参数,即proxyTargetClass;当proxyTargetClass设置为true和false时,对应使用的代理机制大致如下:true目标对象实现接口——使用CGLIB代理机制目标对象没有接口(只有实现类)——使用CGLIB代理机制false目标对象实现接口——使用JDK动态代理机制(代理所有实现的接口)目标对象没有接口(只有实现类)——使用CGLIB代理机制线程池相应的AOP对象创建逻辑介绍;其实AOP拦截具体方法的主要目的是将执行逻辑丢到线程池中执行。那么这就会涉及到本节的主题,也就是线程池。本节需要澄清几个问题:线程池是什么时候创建的?创建的线程池是什么类型的?方法执行任务是如何提交的?创建AnnotationAsyncExecutionInterceptor时初始化线程池创建AnnotationAsyncExecutionInterceptor对象时完成线程池的创建,代码如下:复制代码在其父类AsyncExecutionAspectSupport中创建一个特定的线程池this.defaultExecutor=newSingletonSupplier<>(defaultExecutor,(this)->get(DefaultExecutor.beanFactory));复制代码在getDefaultExecutor方法中,它会先从Spring容器中找到TaskExecutor类型的ThreadPoolBean。如果找不到,它会扩大范围寻找Executor类型的ThreadPoolBean。如果找不到它,它将返回null。这里是一个延迟加载的操作,即只有调用异步方法时,才会触发SingletonSupplier的get操作,从而触发getBean的逻辑。如果在调试的时候没有正常到断点,可以关注一下这个场景。默认线程池SimpleAsyncTaskExecutor@Override@NullableprotectedExecutorgetDefaultExecutor(@NullableBeanFactorybeanFactory){ExecutordefaultExecutor=super.getDefaultExecutor(beanFactory);return(defaultExecutor!=null?defaultExecutor:newTaskSimpleAsync)Executor}看,如果从Spring容器中没有找到对应的线程池bean,则创建SimpleAsyncTaskExecutor作为默认线程池。此类还通过定义新bean来自定义Executor。在这里,该方法被命名为taskExecutor,因为这是Spring搜索的特定方法名称。在我们的例子中,我们希望将并发线程的数量限制为两个,并将队列的大小限制为500。您可以调整更多的东西。如果您没有定义Executorbean,Spring会创建一个SimpleAsyncTaskExecutor并使用它。方法执行任务的提交根据前面的分析,方法执行任务的提交必须在拦截@Async注解时发生,即AnnotationAsyncExecutionInterceptor;通过分析代码,在其父类AsyncExecutionInterceptor中验证了分析。以下是部分核心逻辑:publicObjectinvoke(finalMethodInvocationinvocation)throwsThrowable{//1.获取Method//2.根据Method获取executorAsyncTaskExecutorexecutor=determineAsyncExecutor(userDeclaredMethod);//3.创建一个方法来执行任务taskCallable