事務(wù)基于@Transactional注解和AOP(動態(tài)代理)
1. 動態(tài)代理失效
對于基于接口動態(tài)代理的 AOP 事務(wù)增強來說,由于接口的方法都必然是 public 的,這就要求實現(xiàn)類的實現(xiàn)方法也必須是 public 的(不能是 protected、private 等),同時不能使用 static 的修飾符。所以,可以實施接口動態(tài)代理的方法只能是使用 public 或 public final 修飾符的方法,其他方法不可能被動態(tài)代理,相應(yīng)的也就不能實施 AOP 增強,換句話說,即不能進行 Spring 事務(wù)增強了。
基于 CGLib 字節(jié)碼動態(tài)代理的方案是通過擴展被增強類,動態(tài)創(chuàng)建其子類的方式進行 AOP 增強植入的。由于使用 final、static、private 修飾符的方法都不能被子類覆蓋,相應(yīng)的,這些方法將無法實施 AOP 增強。所以方法簽名必須特別注意這些修飾符的使用,以免使方法不小心成為事務(wù)管理的漏網(wǎng)之魚。
2. AOP失效
第一種(要增強的類或方法沒被spring管理)
對于傳統(tǒng)的web項目來說,通常使用spring和springmvc,因此對于這種項目來講,他是有兩個容器的,一個是spring容器,一般我們會把Service層的東西注入到spring容器中,另一個是springmvc的容器,通常這個容器里注入的是Controller層的東西,這里我們認為spring容器是父容器,springmvc是子容器的概念,然后我們大家都知道通過父子繼承關(guān)系可知,子容器是可以讀取到父容器中的東西,但是父容器是無法讀到子容器中的內(nèi)容,因此基于這個場景,有的同學,把Aop的實現(xiàn)類注入到了spring容器中,并且將Aop的切點表達式配置aop:config <aop:pointcut的execution也配到了spring容器的xml,而巧了這位同學要切的類方法,正好是Controller,也就是springmvc容器中的東西,那么這時候問題就來了,aop在初始化時會在自己的容器中尋找能夠匹配的類方法,然后給他套上一層代理,此時他在自己能夠訪問到的spring容器中根本找不到與之匹配的類和方法,因為這些類和方法是在springmvc容器中管理的,因此就沒有代理成功
解決:那么對于上述問題要怎么修改呢?只需要確保你要Aop切的類和方法與你Aop配置切點aop:config <aop:pointcut的execution表達式聲明是在同一個容器中即可,此時只需要將這個配置移到springmvc容器的xml中即可
第二種(要被增強的類或方法同時被spring和springMVC掃描)
第二種情況與第一種情況有些許的類似,但并不相同,是關(guān)于重復(fù)掃描的,比如你在spring容器中配置了一個Aop,并且把他托管給spring容器管理,而且execution表達式切的也是spring容器中管理的類和方法,理論上這個時候是好用的,這批execution切到的類都被加了代理,但是巧了,springmvc容器中由于配置的是包路徑掃描,恰好把execution表達式切的這一批對象又掃了一遍,又都托管給了springmvc容器,而此時掃到的這批對象,是重新new出來交給springmvc管理的,因此并沒有被aop代理,所以在使用時,注入進來的可能是springmvc容器管理的這批對象,因此使用時發(fā)現(xiàn)Aop代理失效了
解決:這個問題的解決方案,就是避免兩個容器重復(fù)掃描。
第三種(要增強的方法被同類的方法調(diào)用)
第三個問題就比較簡單了,他的現(xiàn)象是有些方法被Aop代理成功了,但有個別方法沒有代理成功,究其原因發(fā)現(xiàn)這部分沒有代理成功的方法并不是通過代理對象調(diào)用的,而是自身調(diào)用的,故被調(diào)用的方法沒有被Aop代理,無法織入橫切邏輯。
解決:舉個栗子,比如A.a(),A.b()是被代理的類和方法,那么當我調(diào)用A.a()時,此時a被代理了,成功執(zhí)行代理類的內(nèi)容,但還沒有完,a()方法中調(diào)用了自身的方法b(),此時我們以為b也會被代理類代理,但實際上并沒有,因為他是自身方法調(diào)用了并不是通過代理類A調(diào)用的,在a方法中可以通過((A) AopContext.currentProxy()).b()調(diào)用,不過前提是配置上<aop:config expose-proxy=“true”>,expose-proxy="true"是重點(先開啟cglib代理,開啟 exposeProxy = true,暴露代理對象)
第四種(用的注解方式?jīng)]有開啟注解支持)
這種就更好理解了,只需要開啟注解支持就行了。
xml方式開啟在spring配置文件添加上aop:aspectj-autoproxy/即可
注解方式開啟在啟動類上添加@EnableAspectJAutoProxy即可
總結(jié)
第一種和第二種是因為MVC分層沒有用好,接收數(shù)據(jù)和業(yè)務(wù)邏輯要分開,
第三種是因為代理模式限制
第四種就是使用不當了文章來源:http://www.zghlxwxcb.cn/news/detail-551591.html
3. @Transactional失效
事務(wù)基于注解和AOP,注解失效和AOP失效
原因一:沒有開啟事務(wù)管理
原因二:標注了@Transactional的方法里面的異常被捕獲了
原因三:標注了@Transactional的方法發(fā)生了非Error 或者 非RuntimeException
原因四:標注了@Transactional的方法的事務(wù)傳播類型propagation配置成了NOTSUPPORT
原因五:標注了@Transactional的方法的事務(wù)傳播類型propagation配置成了NEVER
原因六:標注了@Transactional的方法的事務(wù)傳播類型propagation配置成了SUPPORTS且當前沒有事務(wù)
原因七:外部調(diào)用方法A,A內(nèi)部調(diào)用方法B,A沒有@Transaction注解而B有@Transactional注解
原因九:標注了@Transactional的方法不是public的
原因十:標注了@Transactional的方法發(fā)生的異常不是rollbackFor指定的類型或子類
原因十一:數(shù)據(jù)庫不支持事務(wù)文章來源地址http://www.zghlxwxcb.cn/news/detail-551591.html
到了這里,關(guān)于spring動態(tài)代理失效,AOP失效,事務(wù)@Transactional失效原因的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!