概述
網(wǎng)站建設哪家好,找創(chuàng)新互聯(lián)!專注于網(wǎng)頁設計、網(wǎng)站建設、微信開發(fā)、微信小程序、集團企業(yè)網(wǎng)站建設等服務項目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了敦煌免費建站歡迎大家使用!
在前面一篇文章中,介紹,在一個Bean中注入自己,如果有@Async和@Transaction,如果使用@Autowire注入自身,會報循環(huán)依賴,如果使用BeanFactoryAware注入自己,會使得@Transaction失效。 例如:
@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); } }
當時只是簡單提了一下,這篇文章就是來介紹為什么會失效。
一般情況
造成上面的情況需要滿足以下條件:
造成的結(jié)果:除@Async外的注解生效,其他的都不生效,如下圖
而正常代理的應該是下圖:
原因
首先想到的是@Async注解的處理方式可能和其他的不一樣。在AsyncAnnotationBeanPostProcessor的實現(xiàn)中(具體代碼是在其父類AbstractAdvisingBeanPostProcessor),發(fā)現(xiàn)一個問題,
正常情況下,進來的bean已經(jīng)是被代理的動態(tài)代理類,而失效的時候,進來的確實實際的類,如下圖:
然后在分析下代碼,如果是實際的類,走到69行的時候,返回是true,把@Aysnc的Advisor加入到動態(tài)道理中,而如果是實際的類,走到83行的時候,就會創(chuàng)建代理類,只把@Aysnc的advisor加入到動態(tài)代理中,所已諸如@Transaction就會失效。
為什么進來的不是代理類
其實唯一的區(qū)別就是BeanFactoryAware中,是否通過了BeanFactory獲取了自己。那為什么使用BeanFactory獲取了自己,后續(xù)的BeanPostProcessor中就不是代理了?如果熟悉Spring @Transaction加載機制的就知道,諸如@Transaction,@Retryable 注解的動態(tài)代理創(chuàng)建是在AnnotationAwareAspectJAutoProxyCreator中創(chuàng)建的。通過debug發(fā)現(xiàn),經(jīng)過AnnotationAwareAspectJAutoProxyCreator后,我們的動態(tài)代理竟然沒有加上。
再看一下AnnotationAwareAspectJAutoProxyCreator中的實現(xiàn),但是經(jīng)過他卻沒有生成代理類。原因竟然是提前暴露的Map里面竟然有“myService”,
他是什么時候暴露出來的呢?其實就是在
@Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { self= beanFactory.getBean(MyService.class); }
那么,一切水落石出了,在實例MyService中,觸發(fā)了BeanFactoryAware,通過beanFactory.getBean(MyService.class);中創(chuàng)建了代理類(tips:當前代理類并沒有包含@Async的Adivisor),因為現(xiàn)在Spring其實正是在創(chuàng)建MyService這個Bean,還沒有放入到BeanFactory中。然后我們再這個過程中又觸發(fā)了一次beanFactory.getBean(MyService.class);導致創(chuàng)建代理并返回后,加入到了到了提前暴露的map中。導致后面的一系列問題。感覺有點繞??磮D說話:
正常情況,應該是如下流程:
異常情況卻是這樣的
小結(jié)
正常情況下,還是使用@Autowire來注入把(如果使用Autowire,上述情況直接回拋出循環(huán)依賴)。當然,出現(xiàn)了問題,也是不能放過了,要知其然還要知其所以然!
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。