关于Spring注解@Async引起其余注解失效

概述

在前面一篇文章中,介绍,在一个Bean中注入本身,若是有@Async和@Transaction,若是使用@Autowire注入自身,会报循环依赖,若是使用BeanFactoryAware注入本身,会使得@Transaction失效。 例如:async

@Service public class MyService implements BeanFactoryAware{ private MyService self; //事务注解无效
 @Transactional public void notWork() { ... } @Async public Future async(){ ... } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { self= beanFactory.getBean(MyService.class); } }

当时只是简单提了一下,这篇文章就是来介绍为何会失效。ide

通常状况

形成上面的状况须要知足如下条件:spa

  1. 有@Async和其余相似@Transaction注解
  2. 本身类在BeanFactoryAware中,经过BeanFactory获取本身

形成的结果:除@Async外的注解生效,其余的都不生效,以下图debug

 

而正常代理的应该是下图:3d

缘由

首先想到的是@Async注解的处理方式可能和其余的不同。在AsyncAnnotationBeanPostProcessor的实现中(具体代码是在其父类AbstractAdvisingBeanPostProcessor),发现一个问题, 代理

正常状况下,进来的bean已是被代理的动态代理类,而失效的时候,进来的确实实际的类,以下图:code

 而后在分析下代码,若是是实际的类,走到69行的时候,返回是true,把@Aysnc的Advisor加入到动态道理中,而若是是实际的类,走到83行的时候,就会建立代理类,只把@Aysnc的advisor加入到动态代理中,所已诸如@Transaction就会失效。blog

为何进来的不是代理类

其实惟一的区别就是BeanFactoryAware中,是否经过了BeanFactory获取了本身。那为何使用BeanFactory获取了本身,后续的BeanPostProcessor中就不是代理了?若是熟悉Spring @Transaction加载机制的就知道,诸如@Transaction,@Retryable 注解的动态代理建立是在AnnotationAwareAspectJAutoProxyCreator中建立的。经过debug发现,通过AnnotationAwareAspectJAutoProxyCreator后,咱们的动态代理居然没有加上。事务

再看一下AnnotationAwareAspectJAutoProxyCreator中的实现,可是通过他却没有生成代理类。缘由居然是提早暴露的Map里面居然有“myService”, ip

 

他是何时暴露出来的呢?其实就是在

@Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { self= beanFactory.getBean(MyService.class); }

那么,一切水落石出了,在实例MyService中,触发了BeanFactoryAware,经过beanFactory.getBean(MyService.class);中建立了代理类(tips:当前代理类并无包含@Async的Adivisor),由于如今Spring其实正是在建立MyService这个Bean,尚未放入到BeanFactory中。而后咱们再这个过程当中又触发了一次beanFactory.getBean(MyService.class);致使建立代理并返回后,加入到了到了提早暴露的map中。致使后面的一系列问题。感受有点绕。看图说话:

正常状况,应该是以下流程:

异常状况倒是这样的

 

 

小结

正常状况下,仍是使用@Autowire来注入把(若是使用Autowire,上述状况直接回抛出循环依赖)。固然,出现了问题,也是不能放过了,要知其然还要知其因此然!

相关文章
相关标签/搜索