在前面一篇文章中,介绍,在一个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
形成的结果:除@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,上述状况直接回抛出循环依赖)。固然,出现了问题,也是不能放过了,要知其然还要知其因此然!