1. 程式人生 > >@Async,@Transational註解失效的原因和解決方法

@Async,@Transational註解失效的原因和解決方法

在同一個類中,一個方法呼叫另外一個有註解(比如@Async,@Transational)的方法,註解是不會生效的。比如,下面程式碼例子中,有兩方法,一個有@Transational註解,一個沒有。如果呼叫了有註解的addPerson()方法,會啟動一個Transaction;如果呼叫updatePersonByPhoneNo(),因為它內部呼叫了有註解的addPerson(),如果你以為系統也會為它啟動一個Transaction,那就錯了,實際上是沒有的。
  1. @Service
  2. publicclass PersonServiceImpl implements PersonService {  
  3.  @Autowired
  4.  PersonDao personDao;  
  5.  @Override
  6.  @Transactional
  7.  publicboolean addPerson(Person person) {  
  8.   boolean result = personDao.insertPerson(person)>0 ? true : false;  
  9.   return result;  
  10.  }  
  11.  @Override
  12.  //@Transactional
  13.  publicboolean
     updatePersonByPhoneNo(Person person) {  
  14.   boolean result = personDao.updatePersonByPhoneNo(person)>0 ? true : false;  
  15.   addPerson(person); //測試同一個類中@Transactional是否起作用
  16.   return result;  
  17.  }  
  18. }  
如何檢視是否啟動了Transaction?設定log leve為debug,可以檢視是否有下面這個log,判斷是否啟動了Transaction:DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Creating new transaction with name...同樣地,@Async等其他註解也有這樣的問題。原因:spring 在掃描bean的時候會掃描方法上是否包含@Transactional註解,如果包含,spring會為這個bean動態地生成一個子類(即代理類,proxy),代理類是繼承原來那個bean的。此時,當這個有註解的方法被呼叫的時候,實際上是由代理類來呼叫的,代理類在呼叫之前就會啟動transaction。然而,如果這個有註解的方法是被同一個類中的其他方法呼叫的,那麼該方法的呼叫並沒有通過代理類,而是直接通過原來的那個bean,所以就不會啟動transaction,我們看到的現象就是@Transactional註解無效。為什麼一個方法a()呼叫同一個類中另外一個方法b()的時候,b()不是通過代理類來呼叫的呢?可以看下面的例子(為了簡化,用偽程式碼表示):
  1. @Service
  2. class A{  
  3.     @Transactinal
  4.     method b(){...}  
  5.     method a(){    //標記1
  6.         b();  
  7.     }  
  8. }  
  9. //Spring掃描註解後,建立了另外一個代理類,併為有註解的方法插入一個startTransaction()方法:
  10. class proxy$A{  
  11.     A objectA = new A();  
  12.     method b(){    //標記2
  13.         startTransaction();  
  14.         objectA.b();  
  15.     }  
  16.     method a(){    //標記3
  17.         objectA.a();    //由於a()沒有註解,所以不會啟動transaction,而是直接呼叫A的例項的a()方法
  18.     }  
  19. }  

當我們呼叫A的bean的a()方法的時候,也是被proxy$A攔截,執行proxy$A.a()(標記3),然而,由以上程式碼可知,這時候它呼叫的是objectA.a(),也就是由原來的bean來呼叫a()方法了,所以程式碼跑到了“標記1”。由此可見,“標記2”並沒有被執行到,所以startTransaction()方法也沒有執行。瞭解了失效的原因,解決的方法就簡單了(兩種):
  1. 把這兩個方法分開到不同的類中;
  2. 把註解加到類名上面;
參考:(原創文章,轉載請註明轉自:http://blog.csdn.net/clementad)

相關推薦

@Async@Transational註解失效原因解決方法

在同一個類中,一個方法呼叫另外一個有註解(比如@Async,@Transational)的方法,註解是不會生效的。比如,下面程式碼例子中,有兩方法,一個有@Transational註解,一個沒有。如果呼叫了有註解的addPerson()方法,會啟動一個Transaction;

varnish快取503錯誤400錯誤的原因解決方法

出現400錯誤是因為varnish認為客戶端請求header行數及長度過大,其預設最大接受的請求header行數為64,最大長度(所有請求header行長度之和)為2048,解決這個問題比較簡單,在varnish啟動引數中加入: -p http_max_hdr=256 -p http_req_hdr_le

在同一個類中一個方法呼叫另外一個有註解(比如@Async@Transational)的方法註解失效原因解決方法

在同一個類中,一個方法呼叫另外一個有註解(比如@Async,@Transational)的方法,註解是不會生效的。 比如,下面程式碼例子中,有兩方法,一個有@Transational註解,一個沒有。如果呼叫了有註解的addPerson()方法,會啟動一個Transaction;如果呼叫updatePerso

反射呼叫Service層方法@Autowired註解失效。問題解決

反射呼叫方法時,裡面的dao層註解失敗。空指標異常。 原因很簡單,反射和new有點像。沒通過spring管理。 解決方案1: @Service public class service { @Autowired private Mapper mapper; //新

mysql 直接從date 資料夾備份表還原資料庫之後提示 table doesn`t exist的原因解決方法

如型別是MyISAM, 資料檔案則以”Table.frm””Table.MYD””Table.MYI””三個檔案儲存於”/data/$databasename/”目錄中.如型別是InnoDB, 資料檔案則儲存在”$innodb_data_home_dir/″中的ibdat

centos安裝docker源ubuntu:16.04版本後無法使用iptables命令原因解決方法

Dcoker容器在使用的過程中,有的時候是需要使用在容器中使用iptables進行啟動的,預設的docker run時都是以普通方式啟動的,沒有使用iptables的許可權,那麼怎樣才能在容器中使用iptables呢?要如何開啟許可權呢? 那麼在docker進

webDriver定位不到元素常見原因解決方法

webDriver常用來做ui自動化,但對於一些頁面上的元素,通過WebDriver封裝的findElement方法獲取不到 一、可能原因:     1、元素定位時使用xpath、id、name等方法,引數錯誤     2、定位元素時,頁面載入未完成,或者依賴頁面js載入完

java中Date date = new Date();不能使用Date()不能寫無參的原因解決方法

如果遇到這種情況,其實原因很簡單,如果你是想獲取當前時間使用,報錯的原因是包引的import java.sql.Date; 只需要換成 import java.util.Date; 即可 通過Date類來獲取當前時間 : Date date = new Da

設定JDK環境變數後無法生效的原因解決辦法

最開始安裝過安裝版的JDK版本,然後修改環境變數並不能生效,例如一開始安裝了1.8的版本,後修改環境變數為1.7,命令cmd 裡java -version仍顯示1.8   這是因為當使用安裝版本的JDK程式時,在安裝結束後安裝程式會自動將java.exe、javaw.exe

angularJS報錯$apply already in progress的原因解決方法

$apply eap module 關註 當前 typeof else ply 沒有 如果我們使用了AngularJS中的$scope.$apply()或者$scope.$digest(),我們很可能會遇到類似下面的錯誤,雖然這個錯誤沒有太大影響,但是在日誌中看起來還是很不

MySQL的Illegal mix of collationsy異常原因解決方法

ear 代碼 clear 今天 tag 類型 資料 bsp net 原創 2008年12月25日 11:54:00 標簽: mysql / collation / character / variables / database / server 今天

[python]命令窗口顯示不是內部或外部命令的原因解決方法

命令 所在 dos 今天 屬性 add 系統 進入 文件 今天做習題時總是提示錯誤“不是內部或外部命令,也不是可運行的程序……” 於是上網搜索了一下出現這個錯誤的原因和解決方法,在此做個總結。 原因一:沒有設置PATH環境變量   Windows會根據設置的Path環境

關於網站開發中div標簽中設置寬度後其中文本溢出的原因解決方法

lan 解析 info tro 情況 href targe 圖片 com 一.問題產生的原因   當我們為div標簽聲明了寬度,但是仍然會出現文本越界的情況,不知道大家有沒有發現,只有文本內容為單詞或者純數字 的時候才會出現這種情況為此我特意測試了兩種情況,結果如下:

WPF 程序無法觸摸操作?我們一起來找原因解決方法

line 坐標 團隊 github webkit pro rgba alter 徹底 原文:WPF 程序無法觸摸操作?我們一起來找原因和解決方法! 版權聲明:本作品采用知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議進行許可。歡

配置MySQL時遇到的一些問題解決方法

Q1.配置好路徑和環境變數以後,準備安裝mysql,但是顯示MySQL服務無法啟動 A:網上查了好多解決辦法,最後解決辦法是需要初始化,操作步驟為: mysql -remove mysql -install mysql -initialize Q2.正常啟動mysql後,輸入

Brian模擬器關於MagicError的原因解決方法

檢視官方文件:https://brian2.readthedocs.io/en/2.0rc/user/running.html 對於構建的SNN,Brian有多種執行方法,在大多數簡單的模擬中,您不必顯式地建立Network物件(參考官方手冊intro3-simulator有用到Network的

開啟網頁速度慢的原因解決方法

開啟網頁打不開,開啟速度慢的原因和解決方法 1、原因一: 載入資源過多,http請求太多,佔用伺服器資源越多,時間越久,支援不了併發量,伺服器承受不了太多請求,開始丟棄部分資料,網頁無法開啟,報錯404 解決:減少http請求次數 2、原因二:接收資料時間過長,如下載資源過

Win10 開始運行不保存歷史記錄原因解決方法

需要 regedit 方法 打開 搜索 選擇 設置 運行 一個 在Win10 1703的時候你也許會發現開始運行以後,再次打開就沒有任何歷史記錄了,常規方法是桌面-右鍵-個性化-開始-顯示最常用的應用..可是打開是灰色的不可選..其實這個問題很好解決,在win10 1506

wordpress更改“固定連結”模式後頁面出現404原因解決方法

Nginx 解決方案: 在 /etc/nginx/config.d/mysit.conf檔案的 loction \ {} 中新增 if (-f $request_filename/index.html){ rewrite (.*) $1/index.html break; }

ConcurrentModificationException: 集合異常——產生原因解決方法

:注意事項:迭代器在使用的時候,有人為了方便,如下使用就會有問題 System.out.println(((Student)it.next()).getName()+”---”+((Student)it.next()).getAge()); 注意事項:迭代器在使用的時候,有人為了方便,如下使