一.背景:spring提供了@Async异步注解,使得方法的调用可以异步的进行,下面代码提供简单的演示:
@Configuration @EnableAsync @ComponentScan("com.yang.xiao.hui.aop") public class App { public static void main(String[] args) { ApplicationContext ctx = new AnnotationConfigApplicationContext(App.class); MyAsync service = ctx.getBean(MyAsync.class); System.out.println(service.getClass()); service.async1(); System.out.println("目标方法执行完没........."); } } @Component public class MyAsync { @Async public void async1() { try { TimeUnit.SECONDS.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("hello1:"+this.getClass()); } public void async2(){ System.out.println("hello2:"+this.getClass()); this.async1(); } }
上述代码提供了最简单的异步使用方式,如果是同步执行,那么控制台打印的顺序应该是:
System.out.println("hello1:"+this.getClass())-------》 System.out.println("目标方法执行完没.........");
然而控制台的打印刚好相反,证明异步的注解生效了:
二.原理分析
1.猜想:aync1()方法标注了@Async注解,该方法就异步执行了,那么该方法肯定是被拦截了,方法拦截肯定存在一个方法拦截器MethodInterceptor
方法拦截器是一个接口,对异步方法的拦截,肯定是该接口的一个实现类,如何找到它:
2.线索分析:我们的唯一条件是主启动类上贴了一个@EnableAsync注解
点击进去分析:
根据追踪,我们发现,最终会往容器中注入 AsyncAnnotationBeanPostProcessor
分析其继承体体系,发现其实现了BeanFactoryAware接口,实现该接口的类,spring容器在创建该bean时,会回调:void setBeanFactory(BeanFactory beanFactory) throws BeansException;
接着我们看看:
我们之后看看AsyncAnnotationAdvisor的创建过程:
接着看this.advice = buildAdvice(executor, exceptionHandler);
至此,我们终于找到方法拦截器了,为何是它,看看它的继承体系:
3.验证:既然找到了方法拦截器,那么我们就打断点在拦截方法里,执行之前的测试代码:拦截方法在它的父类中:AsyncExecutionInterceptor
原文:https://www.cnblogs.com/yangxiaohui227/p/14831911.html