您好,登錄后才能下訂單哦!
spring service層調用同類中的方法是什么,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。
有這樣的一道面試題:在service層調用別的service層的方法,他們的事務能否生效;如果是在同一個類中調用帶有@Transactional注解的方法,此時,他們的事務能否生效?
看了許多大神的blog,今天來做一下總結:
先給出大家答案:
不同類之間的方法調用,如類A的方法a()調用類B的方法b(),這種情況事務是正常起作用的。只要方法a()或b()配置了事務,運行中就會開啟事務,產生代理(注意是不同的類,如果是類A方法a()調用類A方法b(),那么只有a()配置了事務才會有效)。
同一類內方法調用,無論被調用的b()方法是否配置了事務,此事務在被調用時都將不生效。
(1) 首先先說一下Spring事務管理詳解:下面的這篇博客介紹的很清楚了,從基本原理、事務的特性、隔離級別以及事務實現的三種方式
Spring事務管理詳解
https://blog.csdn.net/donggua3694857/article/details/69858827
(2) 知道了事務的一些知識后,下面說一下@Transactional注解的信息(大家著重看一下4 5 6條的解釋)
1.在需要事務管理的地方加@Transactional 注解。@Transactional 注解可以被應用于接口定義和接口方法、 類定義和類的 public 方法上。 2.@Transactional 注解只能應用到 public 可見度的方法上。 如果你在 protected、private 或者 package-visible 的方法上使用 @Transactional 注解,它也不會報錯, 但是這個被注解的方法將不會展示 已配置的事務設置。 3.注意僅僅 @Transactional 注解的出現不足于開啟事務行為,它僅僅 是一種元數據。 必須在配置文件中使用配置元素,才真正開啟了事務行為。(spring配置文件中,開啟聲明式事務) 例如可以這么配置: <!--======= 事務配置 Begin ================= --> <!-- 事務管理器(由Spring管理MyBatis的事務) --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!-- 關聯數據源 --> <property name="dataSource" ref="dataSource"></property> </bean> <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" /> <!--======= 事務配置 End =================== --> 4.通過 元素的 “proxy-target-class” 屬性值來控制是基于接口的還是基于類的代理被創建。 如果 “proxy-target-class” 屬值被設置為 “true”,那么基于類的代理將起作用(這時需要CGLIB庫 cglib.jar在CLASSPATH中)。如果 “proxy-target-class” 屬值被設置為 “false” 或者這個屬性被省略, 那么標準的JDK基于接口的代理將起作用。 5.Spring團隊建議在具體的類(或類的方法)上使用 @Transactional 注解,而不要使用在類所要實現的任何接口 上。在接口上使用 @Transactional 注解,只能當你設置了基于接口的代理時它才生效。因為注解是 不能繼承 的,這就意味著如果正在使用基于類的代理時,那么事務的設置將不能被基于類的代理所識別,而且對象也將不會被事 務代理所包裝。 6.@Transactional的事務開啟 ,或者是基于接口的 或者是基于類的代理被創建。所以在同一個類中一個無事務的方法 用另一個有事務的方法,事務是不會起作用的。如果在有事務的方法中調用另外一個有事務的方法,那么事務會起作用, 并且共用事務。如果在有事務的方法中調用另外一個沒有事務的方法,那么事務也會起作用。
不生效的原因:
當從類外調用沒有添加事務的方法a()時,從spring容器獲取到的serviceImpl對象實際是包裝好的proxy對象,因此調用a()方法的對象是動態代理對象。而在類內部a()調用b()的過程中,實質執行的代碼是this.b(),此處this對象是實際的serviceImpl對象而不是本該生成的代理對象,因此直接調用了b()方法。
解決辦法:
1. 放到不同的類中進行調用 2. 在spring配置文件中加入配置 <aop:aspectj-autoproxy/> <aop:aspectj-autoproxy proxy-target-class=“true” expose-proxy=“true” /> 3. 將之前使用普通調用的方法,換成使用代理調用 ((TestService)AopContext.currentProxy()).testTransactional2(); 獲取到TestService的代理類,再調用事務方法,強行經過代理類,激活事務切面。 4. 使用異步操作,另外開啟一個線程或者將這個消息寫入到隊列里面,在其他的地方進行處理
關于spring service層調用同類中的方法是什么問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。