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

565 阅读2分钟

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

2.2.6、ComposablePointcut切点

AnnotationMatchingPointcut : 针对于指定的类上注解、方法上注解 。依不同构造方法的入参来指定注解类型 ComposablePointcut : 组合用法。 可以(intersection 交集 或 union 并集)多个pointcut, ClassFilter、 MethodMatcher

   ComposablePointcut result = null;
   for (Class<? extends Annotation> asyncAnnotationType : asyncAnnotationTypes) {
      Pointcut cpc = new AnnotationMatchingPointcut(asyncAnnotationType, true);
      Pointcut mpc = new AnnotationMatchingPointcut(null, asyncAnnotationType, true);
      if (result == null) {
         result = new ComposablePointcut(cpc);
      }
      else {
         result.union(cpc);
      }
      result = result.union(mpc);
   }
   return (result != null ? result : Pointcut.TRUE);
}

对于单个pointcut由MethodMatcher (方法匹配)与 ClassFilter (类匹配)组合构成。 img

2.2.7、调用入口

回到AsyncAnnotationBeanPostProcessor,其父类AbstractBeanFactoryAwareAdvisingPostProcessor不仅仅继承BeanFactoryAware, 而且还实现了BeanPostProcessor接口!

PS: 后置处理器,在Spring容器的创建过程中(具体为Bean初始化前后)会回调BeanPostProcessor中定义的两个方法 在执行postProcessAfterInitialization方法内, 通过isEligible 方法对bean进行判定是否需要构建代理

public Object postProcessAfterInitialization(Object bean, String beanName) {
   if (this.advisor == null || bean instanceof AopInfrastructureBean) {
      // Ignore AOP infrastructure such as scoped proxies.
      return bean;
   }

   if (bean instanceof Advised) {
      Advised advised = (Advised) bean;
      if (!advised.isFrozen() && isEligible(AopUtils.getTargetClass(bean))) {
         // Add our local Advisor to the existing proxy's Advisor chain...
         if (this.beforeExistingAdvisors) {
            advised.addAdvisor(0, this.advisor);
         }
         else {
            advised.addAdvisor(this.advisor);
         }
         return bean;
      }
   }

   if (isEligible(bean, beanName)) {
      ProxyFactory proxyFactory = prepareProxyFactory(bean, beanName);
      if (!proxyFactory.isProxyTargetClass()) {
         evaluateProxyInterfaces(bean.getClass(), proxyFactory);
      }
      proxyFactory.addAdvisor(this.advisor);
      customizeProxyFactory(proxyFactory);
      return proxyFactory.getProxy(getProxyClassLoader());
   }

   // No proxy needed.
   return bean;
}

会优先通过Pointcut的ClassFilter进行判定, 其次是MethodMatcher! img img img

2.3、总结

@Async注解使用默认模式时,本质是代理,动态代理就是在运行期间,动态的生成了一个class在 jvm 中,然后通过这个class的实例调用真正的实现类的方法,所以必须获取被代理对象,代理才能生效;

如下方式会使@Async失效:

  1. 异步方法使用static修饰
  2. 异步类没有使用@Component注解(或其他注解)导致spring无法扫描到异步类
  3. 异步方法不能与被调用的异步方法在同一个类中
  4. 类中需要使用@Autowired或@Resource等注解自动注入,不能自己手动new对象
  5. 如果使用SpringBoot框架必须在启动类 or 配置类中增加@EnableAsync注解