javascript
spring 事务原理_Spring声明式事务处理的实现原理,来自面试官的穷追拷问
公眾號[JavaQ]原創,專注分享Java基礎原理分析、實戰技術、微服務架構、分布式系統構建,誠邀點贊關注!
面試官:有如下代碼場景,A類的a1方法沒有標注@Transactional注解,a2方法標注了@Transactional注解,那么在a1方法里調用a2方法,此時會開始事務嗎?
小小白:不會開啟事務。
面試官:解釋一下為什么?
小小白:a1方法是目標類A的原生方法,調用a1的時候即直接進入目標類A進行調用,在目標類A里面只有a2的原生方法,在a1里調用a2,即直接執行a2的原生方法,并不通過創建代理對象進行調用,所以并不會進入TransactionInterceptor的invoke方法,不會開啟事務。
面試官:那此時如果在a1方法上標注@Transactional注解,a2方法不標注@Transactional注解,但是a1方法的訪問修飾符是protected,在a1方法里調用a2方法會開始事務嗎?
小小白:也不會開啟事務。
面試官:根據你上面的回答改了代碼,為什么還是不會開啟事務?
小小白:@Transactional的工作機制是基于AOP實現的,而AOP是使用動態代理實現的,動態代理要么是JDK方式、要么是Cglib方式。如果是JDK動態代理的方式,根據上面的分析可以知道,目標類的目標方法是在接口中定義的,也就是必須是public修飾的方法才可以被代理。如果是Cglib方式,代理類是目標類的子類,理論上可以代理public和protected方法,但是Spring在進行事務增強是否能夠應用到當前目標類判斷的時候,遍歷的是目標類的public方法,所以Cglib方式也只對public方法有效。?
面試官:Spring框架中聲明式事務處理是如何實現的?
小小白:Spring容器在初始化每個單例bean的時候,會遍歷容器中的所有BeanPostProcessor實現類,并執行其postProcessAfterInitialization方法,在執行AbstractAutoProxyCreator類的postProcessAfterInitialization方法時會遍歷容器中所有的切面,查找與當前實例化bean匹配的切面,這里會獲取事務屬性切面,查找@Transactional注解及其屬性值,然后根據得到的切面創建一個代理對象,默認是使用JDK動態代理創建代理,如果目標類是接口,則使用JDK動態代理,否則使用Cglib。在創建代理的過程中會獲取當前目標方法對應的攔截器,此時會得到TransactionInterceptor實例,在它的invoke方法中實現事務的開啟和回滾,在需要進行事務操作的時候,Spring會在調用目標類的目標方法之前進行開啟事務、調用異?;貪L事務、調用完成會提交事務。是否需要開啟新事務,是根據@Transactional注解上配置的參數值來判斷的。如果需要開啟新事務,獲取Connection連接,然后將連接的自動提交事務改為false,改為手動提交。當對目標類的目標方法進行調用的時候,若發生異常將會進入completeTransactionAfterThrowing方法。?
面試官:能否通俗的講述一下它的實現原理?
小小白:如果在類A上標注Transactional注解,Spring容器會在啟動的時候,為類A創建一個代理類B,類A的所有public方法都會在代理類B中有一個對應的代理方法,調用類A的某個public方法會進入對應的代理方法中進行處理;如果只在類A的b方法(使用public修飾)上標注Transactional注解,Spring容器會在啟動的時候,為類A創建一個代理類B,但只會為類A的b方法創建一個代理方法,調用類A的b方法會進入對應的代理方法中進行處理,調用類A的其它public方法,則還是進入類A的方法中處理。在進入代理類的某個方法之前,會先執行TransactionInterceptor類中的invoke方法,完成整個事務處理的邏輯,如是否開啟新事務、在目標方法執行期間監測是否需要回滾事務、目標方法執行完成后提交事務等。
面試官:Spring框架對事務回滾的實現,是不是對所有類型的異常都會進行事務回滾操作?
小小白:Spring并不會對所有類型異常都進行事務回滾操作,默認是只對Unchecked Exception(Error和RuntimeException)進行事務回滾操作。
面試官:有沒有遇到過Transactional注解的不合理用法?
小小白:當下對數據庫連接的使用基本上都用連接池技術,每個應用會根據環境和自身需求設置一些合適的連接池配置,如果每個連接都一直被長時間占用,會導致數據庫連接數不夠用、系統各項壓力指標不斷攀升、系統緩慢等問題,所以說連接池中的每一個連接都是很昂貴的。那么問題就來了,只要需要事務就需要占用一個數據庫連接,如果在需要開啟事務的方法里進行一些IO操作、網絡通訊等需要長時間處理的操作,這個數據庫連接就一直被占用著,直到方法執行結束后自動提交事務或執行過程中發生異?;貪L事務,這個數據庫連接才會被釋放掉。這個過程中還有一個很可怕的問題,如果在需要開啟事務的方法里進行了網絡通訊操作,而這個操作沒有設置網絡超時時間,那這個數據庫連接就會被一直占用著。上述問題,在流量很大的情況下簡直就是災難,會直接導致應用系統掛掉。
面試官:如何解決這些問題?
小小白:正確的使用Transactional注解需要做到如下四點:
不要在類上標注Transactional注解,要在需要的方法上標注。即使類的每個方法都需要事務也不要在類上標注,因為有可能你或別人新添加的方法根本不需要事務;
標注了Transactional注解的方法體中不要涉及耗時很久的操作,如IO操作、網絡通信等;
根據業務需要設置合適的事務參數,如是否需要新事務、超時時間等;
控制事務影響的范圍,代碼中減少事務影響的代碼。
往期推薦:
Spring MVC相關面試題就是無底洞,反正我是怕了
說實話,面試這么問Spring框架的問題,我快扛不住了
沒使用加號拼接字符串,面試官竟然問我為什么
面試官一步一步的套路你,為什么SimpleDateFormat不是線程安全的
都說ThreadLocal被面試官問爛了,可為什么面試官還是喜歡繼續問
Java注解是如何玩轉的,面試官和我聊了半個小時
如何去除代碼中的多次if而引發的一連串面試問題
三分鐘快速搞定git常規使用
String引發的提問,我差點跪了
就寫了一行代碼,被問了這么多問題
面試官:JVM對鎖進行了優化,都優化了啥?
synchronized連環問
點點"在看" 唄
總結
以上是生活随笔為你收集整理的spring 事务原理_Spring声明式事务处理的实现原理,来自面试官的穷追拷问的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: web怎么用代码创造表格_Python新
- 下一篇: 浏览器控制台执行代码_JavaScrip