Spring AOP调用本类方法不生效(1)

281 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第25天,点击查看活动详情

1、错误的使用

最近发现有小伙伴在代码里错误的使用@Async注解,这样用是不会生效的;

img

2、为什么不能这样写?

2.1、先看@Async注解使用条件:

@Async注解一般用在类的方法上,如果用在类上,那么这个类所有的方法都是异步执行的; 所使用的@Async注解方法的类对象应该是Spring容器管理的bean对象; 调用异步方法类上需要配置上注解@EnableAsync 默认情况下(即@EnableAsync注解的mode=AdviceMode.PROXY)

2.2、还要了解@EnableAsync 原理

2.2.1、EnableAsync

SpringBoot当要使用@Async时,需启动类显示声明@EnableAsync 来 注入 AsyncConfigurationSelector(一个AdviceModeImportSelector);默认AdviceMode.PROXY

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

   //用户定义的需要进行异步执行的注解,默认只有Async注解
   Class<? extends Annotation> annotation() default Annotation.class;

   //是否创建基于CGLIB的代理对象
   boolean proxyTargetClass() default false;

   //代理模式选择 PROXY表示jdk的代理
   AdviceMode mode() default AdviceMode.PROXY;

   //对应的AsyncAnnotationBeanPostProcessor的拦截顺序
   int order() default Ordered.LOWEST_PRECEDENCE;

}

2.2.2、ProxyAsyncConfiguration

最终注入的是ProxyAsyncConfiguration

   private static final String ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME =
         "org.springframework.scheduling.aspectj.AspectJAsyncConfiguration";

   @Override
   @Nullable
   public String[] selectImports(AdviceMode adviceMode) {
      switch (adviceMode) {
         //默认的是jdk PROXY的模式 
         case PROXY:
            return new String[] {ProxyAsyncConfiguration.class.getName()};
         //使用AspectJ的模式
         case ASPECTJ:
            return new String[] {ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME};
         default:
            return null;
      }
   }

}

2.2.3、AsyncAnnotationBeanPostProcessor

构建了一个内部含Advisor的类:AsyncAnnotationBeanPostProcessor。

@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyAsyncConfiguration extends AbstractAsyncConfiguration {

   @Bean(name = TaskManagementConfigUtils.ASYNC_ANNOTATION_PROCESSOR_BEAN_NAME)
   @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
   public AsyncAnnotationBeanPostProcessor asyncAdvisor() {
      Assert.notNull(this.enableAsync, "@EnableAsync annotation metadata was not injected");
      AsyncAnnotationBeanPostProcessor bpp = new AsyncAnnotationBeanPostProcessor();
      //设置executor跟exceptionHandler,spring都是空实现,也就是这两个值都是null,后面会设置默认的对象,也可以自己指定实现,
      bpp.configure(this.executor, this.exceptionHandler);
      Class<? extends Annotation> customAsyncAnnotation = this.enableAsync.getClass("annotation");
      //如果annotation值不是默认的,则将这个加入到AsyncAnnotationBeanPostProcessor,后面进行拦截用
      if (customAsyncAnnotation != AnnotationUtils.getDefaultValue(EnableAsync.class, "annotation")) {
         bpp.setAsyncAnnotationType(customAsyncAnnotation);
      }
      bpp.setProxyTargetClass(this.enableAsync.getBoolean("proxyTargetClass"));
      bpp.setOrder(this.enableAsync.<Integer>getNumber("order"));
      return bpp;
   }

}

AsyncAnnotationBeanPostProcessor 继承了 BeanFactoryAware 接口。在setBeanFactory方法中,初始化了AsyncAnnotationAdvisor