spring的service類呼叫自己方法事務無效

2021-08-21 05:51:07 字數 3432 閱讀 6820

今天在寫**的時候,遇見了乙個非常奇怪的問題,我在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 ...