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