Transaction 在同一個類中不生效


參考:https://blog.csdn.net/qq_30336433/article/details/83338835

 

最近在開發項目中踩到一個坑,以此記錄下來。以備后來人借鑒

 

1、相信使用spring開發的小伙伴對@Transaction這個注解應該不會陌生。

spring提供了非常強大的事務管理機制,之前一直以為只要在方法上加上@Transaction就萬事大吉了

 

 

但是最近發現有些情況下 這個注解會失效。

當這個方法被同一個類調用的時候,spring無法將這個方法加到事務管理中。

 

下面我們來看看為什么會失效?

其實 spring的@Transactional事務生效的一個前提是方法調用前經過攔截器TransactionInterceptor , 也就是說只有通過TransactionInterceptor攔截器的方法才會被加入到Spring事務管理中,

查看spring源碼可以知道,在AdvisedSupport.getInterceptorsAndDynamicInterceptionAdvice方法中會調用方法中獲取@Transactional注解,如果有該注解則啟用事務,否則不啟用注解

 

 

這個方法是通過spring的AOP類CglibAopProxy的內部類DynamicAdviseInterceptor調用的,而DynamicAdvisedInterceptor繼承了MethodInterceptor,用於攔截方法調用,並從中獲取調用鏈。

如果是在同一個類中的方法調用,則不會被方法攔截器攔截到,因此事務不會起作用,必須將方法放入另外一個類中,並且該類通過spring注入

 

總結一下:Transactional是Spring提供的事務管理注解

spring 采用動態代理(AOP)實現對Bean的管理和切片,它為我們的每個class生成一個代理對象,只有在代理對象之間進行調用時,可以觸發切面邏輯。

而在同一個類中,方法B調用A,調用的事元對象的方法,而不是通過代理對象,所以spring無法切到這次調用,也就是無法通過注解保證事務性。

 

解決方案:

    1. 可以將方法放入另一個類,並且該類通過spring注入,即符合了在對象之間調用的條件。
    2. 獲取本對象的代理對象,再進行調用。具體操作如:
      1)Spring-content.xml上下文中,增加配置:<aop:aspectj-autoproxy expose-proxy=“true”/>
      2)在xxxServiceImpl中,用(xxxService)(AopContext.currentProxy()),獲取到xxxService的代理類,再調用事務方法,強行經過代理類,激活事務切面。
    3. 很多時候,方法內調用又希望激活事務,是由於同一個方法既有DAO操作又有I/O等耗時操作,不想讓耗時的I/O造成事務的太長耗時(比如新增商品同時需要寫入庫存)。此時,可以將I/O做成異步操作(如加入線程池),而加入線程池的操作即便加入事務也不會導致事務太長,問題可以迎刃而解。???這條不太懂

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM