最近生產環境發現一個很奇怪的問題,以前用的好好的Spring事務配置在一個接口上忽然失效了,其他接口正常。緣由到底是什麼呢?且聽我慢慢道來。:-)git
問題描述:spring
注:問題的描述是在demo工程中對原問題的模擬,只是爲了說明問題,因此數據看起來有點隨意,請勿見怪。數據庫
數據庫表userinfo中有兩條數據post
配置Sping事務並對兩條記錄進行同時刪除,此時因爲兩條delete中間有一個異常拋出,因此兩條記錄不會被刪除,一切到這仍是很是合乎常理的。測試
走讀問題代碼發現工程中有一個類實現了BeanFactoryPostProcessor接口,而且在postProcessBeanFactory方法中對上面調用的接口調用了getBeansOfType,因而在demo中進行模擬,相似於下面這樣:.net
此時,咱們在demo工程配置MyBeanFactoryPostProcessor對應的bean,從新調用接口中的delete方法,從結果能夠看出,方法中的兩個delete操做已經不在同一事務中了,也就是說Spring事務失效了!代理
問題分析:日誌
MyBeanFactoryPostProcessor的bean存在前,能夠看到對應的事務配置生效,並生成了代理類。接口
而配置MyBeanFactoryPostProcessor以後,沒有事務的代理類生成了,固然事務也就會失效。事務
那麼爲何新加一個實現了BeanFactoryPostProcessor接口的類就會有這個影響呢?
如上圖所示,spring的bean初始化過程當中,會在圖中的1)處調用實現了BeanFactoryPostProcessor的類中的postProcessBeanFactory方法對beanFactory進行後處理
而後執行到圖中的2)處調用BeanPostProcessor的方法攔截bean的建立過程,作一些前置後置處理,spring的aop生成代理類(如本文中的事務切面)就是在這裏完成的
MyBeanFactoryPostProcessor實現了BeanFactoryPostProcessor接口,並在postProcessBeanFactory中調用getBeansOfType完成了對userDao的實例化,執行到2)時
也就不能生成對應的代理類,從而致使了事務配置的實效。上面的分析也能夠從spring的啓動日誌中獲得驗證:
當MyBeanFactoryPostProcessor存在時,在internalAutoProxyCreator以前,userDao的bean已經完成了實例化。
而沒有MyBeanFactoryPostProcessor的狀況下,userDao是能夠生成事務代理類的。
注:AspectJAwareAdvisorAutoProxyCreator實現了BeanPostProcessor接口
最後咱們也能夠從類的註釋說明看出spring是不建議經過實現BeanFactoryPostProcessor來與bean的實例化進行交互的。
測試工程:https://git.oschina.net/zjg23/SpringTransactionTest