概述
在前面一篇文章中,介紹,在一個bean中注入自己,如果有@async和@transaction,如果使用@autowire注入自身,會報循環依賴,如果使用beanfactoryaware注入自己,會使得@transaction失效。 例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
@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 ); } } |
當時只是簡單提了一下,這篇文章就是來介紹為什么會失效。
一般情況
造成上面的情況需要滿足以下條件:
- 有@async和其他類似@transaction注解
- 自己類在beanfactoryaware中,通過beanfactory獲取自己
造成的結果:除@async外的注解生效,其他的都不生效,如下圖
而正常代理的應該是下圖:
原因
首先想到的是@async注解的處理方式可能和其他的不一樣。在asyncannotationbeanpostprocessor的實現中(具體代碼是在其父類abstractadvisingbeanpostprocessor),發現一個問題,
正常情況下,進來的bean已經是被代理的動態代理類,而失效的時候,進來的確實實際的類,如下圖:
然后在分析下代碼,如果是實際的類,走到69行的時候,返回是true,把@aysnc的advisor加入到動態道理中,而如果是實際的類,走到83行的時候,就會創建代理類,只把@aysnc的advisor加入到動態代理中,所已諸如@transaction就會失效。
為什么進來的不是代理類
其實唯一的區別就是beanfactoryaware中,是否通過了beanfactory獲取了自己。那為什么使用beanfactory獲取了自己,后續的beanpostprocessor中就不是代理了?如果熟悉spring @transaction加載機制的就知道,諸如@transaction,@retryable 注解的動態代理創建是在annotationawareaspectjautoproxycreator中創建的。通過debug發現,經過annotationawareaspectjautoproxycreator后,我們的動態代理竟然沒有加上。
再看一下annotationawareaspectjautoproxycreator中的實現,但是經過他卻沒有生成代理類。原因竟然是提前暴露的map里面竟然有“myservice”,
他是什么時候暴露出來的呢?其實就是在
1
2
3
4
|
@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,上述情況直接回拋出循環依賴)。當然,出現了問題,也是不能放過了,要知其然還要知其所以然!
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:http://www.cnblogs.com/lizo/p/8652576.html