今天在寫**的時候,遇見了乙個非常奇怪的問題,我在spring的乙個service方法中呼叫本類中的另乙個方法(該方法並不是實現介面來的方法,只是把重複的**抽出來的,只在本類中使用),事務竟然無效。我用的是宣告式事務,之前是直接將註解標註在controller呼叫的service方法上,由於某種原因,我必須將事務開啟到下面的b方法上,但是將事務移動到b方法上時,事務無效了,大概如下:
package com.ryx.test;
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.stereotype.controller;
@controller
public
class
testcontroller
}
package com.ryx.test;
import org.springframework.stereotype.service;
import org.springframework.transaction.annotation.transactional;
@service
public
class
testservice
public
void
testtransactional_b
()
}
之前事務是這樣的,我是將@transactional 放到了方法a上,方法a是是controller直接呼叫的方法,方法b也是包含在方法a的事務中,事務是可用的,但是我需要將事務只開在b方法上,a方法不需要開啟事務,然後將@transactional註解 移到b方法上,事務失效了。
然後搜尋了一下@transactional註解無效,得到以下有用資訊:
在需要事務管理的地方加
@transactional
註解。@transactional
註解可以被應用於介面定義和介面方法、類定義和類的
public
方法上。
@transactional
註解只能應用到 public
可見度的方法上。 如果你在 protected
、private
或者 package
-visible 的方法上使用 @transactional
註解,它也不會報錯, 但是這個被註解的方法將不會展示已配置的事務設定。
注意僅僅 @transactional
註解的出現不足於開啟事務行為,它僅僅 是一種元資料。必須在配置檔案中使用配置元素,才真正開啟了事務行為。(spring配置檔案中,開啟宣告式事務)
通過 元素的 「proxy-target-class
」 屬性值來控制是基於介面的還是基於類的**被建立。如果 「
proxy
-target
-class
」 屬值被設定為 「
true
」,那麼基於類的**將起作用(這時需要
cglib
庫cglib
.jar
在classpath
中)。如果 「
proxy
-target
-class
」 屬值被設定為 「
false
」 或者這個屬性被省略,那麼標準的
jdk基於介面的**將起作用。
spring團隊建議在具體的類(或類的方法)上使用 @transactional
註解,而不要使用在類所要實現的任何介面上。在介面上使用 @transactional
註解,只能當你設定了基於介面的**時它才生效。因為註解是 不能繼承 的,這就意味著如果正在使用基於類的**時,那麼事務的設定將不能被基於類的**所識別,而且物件也將不會被事務**所包裝。@transactional的事務開啟 ,或者是基於介面的 或者是基於類的**被建立。所以在同乙個類中乙個無事務的方法呼叫另乙個有事務的方法,事務是不會起作用的。
看到了最後一條,在同一類中乙個呼叫本類中另乙個有事務的方法,事務是無效的. 網上也給出了解決方法:
1.將這部分業務**寫到另乙個service中,然後注入呼叫
2.要呼叫**類才會被切進去。
我用的另一種方法
第一步:首先在spring的配置檔案中加入以下配置
第二步:將之前使用普通呼叫的方法,換成使用**呼叫
proxy-target-class="true"
expose-proxy="true" />
((testservice)aopcontext.currentproxy()).testtransactional2();
親測單獨在b方法上開啟事務生效!package com.ryx.test;
import org.springframework.stereotype.service;
import org.springframework.transaction.annotation.transactional;
@service
public
class
testservice
@transactional
public
void
testtransactional_b()
}
原因解析:
參考:只要給目標類testservice 的某個方法加上註解@transactional,spring就會為目標類生成對應的**類,以後呼叫testservice 中的所有方法都會先走**類(即使呼叫未加事務註解的方法a,也會走**類),即在通過getbean(「testservice 「)獲得的業務類時,實際上得到的是乙個**類,假設這個類叫做testserviceproxy ,spring為testservice 生成的**類類似於如下**:
由於目標類中只有testtransactional_b方法加入了事務管理,所以**類中為testtransactional_b方法加入了橫切事務邏輯,spring事務管理的本質是通過aop為目標類生成動態**類,並在需要進行事務管理的方法中加入事務管理的橫切邏輯**(如testservice 中的testtransactional_b方法所示)。
呼叫getbean(「testservice 「).testtransactional_b()時,實際上執行的是testserviceproxy.testtransactional_b(),**類的testtransactional_b方法會通過反射呼叫目標類的testtransactional_b方法
Service類的命令
service命令是redhat linux相容的發行版中用來控制系統服務的實用工具,它以啟動 停止 重新啟動和關閉系統服務,還可以顯示所有系統服務的當前狀態。service 服務名 引數 服務名 服務的名稱 引數 statu 狀態 stop 關閉 start 開始 h 顯示幫助資訊 status ...
Activiti表及操作service類說明
activiti的表的說明 act re 流程定義和流程資源 acr ru 執行時,流程例項 任務 變數 act hi 歷史表 act ge 通用表 activiti的架構 類關係圖 獲取流程引擎工具類 processengines.getdefaultprocessengine 流程引擎可以獲取各...
關於Service呼叫Service 的思考
以前做軟體都是隨便寫幾個service,純粹為了service而service,當某天突然發現我的兩個service竟然需要互相訪問,於是乎開始考慮如何設計service,特別是service之間的依賴關係如何設計的問題,因此偶認為軟體service層的設計應該重點放在兩個方面 一是service ...