溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

spring service層調(diào)用同類中的方法是什么

發(fā)布時間:2021-11-11 09:51:33 來源:億速云 閱讀:219 作者:柒染 欄目:編程語言

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)知識。

向AI問一下細節(jié)

免責(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)容。

AI