關於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,上述狀況直接回拋出循環依賴)。固然,出現了問題,也是不能放過了,要知其然還要知其因此然!

相關文章
相關標籤/搜索