2017-07-27 802 views
3

我有問題: 爲什麼當我們使用@Scheduled@Transaction註釋方法時,事務不起作用? 我知道@Scheduled調用我的類而不是由Spring創建的代理類,但無法理解此行爲。爲什麼@ Scheduled註釋不能用@Transaction註解。 Spring Boot

import org.springframework.scheduling.annotation.Scheduled; 
import org.springframework.transaction.annotation.Transactional; 

@Service 
public class UserServiceImpl implements UserService { 

    @Override 
    @Scheduled(fixedRateString = "${somestring}",initialDelayString = "${anotherstring}") 
    @Transactional 
    public void doSomething() { 

     } 
    } 

我有這個問題的兩個解決方案:從Scheduled方法

  1. 呼叫代理。

  2. 實施ConcurrentTaskScheduler 並與ScheduledMethodRunnable與代理對象替換的ScheduledMethodRunnable對象(即我的同班同學) 。

但是這種解決方案非常不方便。

你可以解釋一下爲什麼@Scheduled是這樣的嗎?

謝謝!

+0

_doesn't_的意思是什麼? –

+0

我的意思是說,如果調度程序調用此方法,那麼方法中沒有事務,用@Transactional註釋。因爲調度程序調用我的類的方法而不是代理類的方法。 –

+0

它可能工作時,你廢除'實現UserService'部分,因爲它應該觸發不同類型的代理:https://stackoverflow.com/a/30489513/995891 – zapl

回答

0

發生這種情況是因爲要處理兩個註釋使用MAGIC。

我想有幾件事情發生:

  1. UserServiceImpl創建。
  2. @Scheduled註釋被處理並且對bean的引用被存儲以在適當的時間調用它。
  3. @Transactional註釋被處理。它創建存儲對原始bean的引用的代理。原始bean被替換爲應用程序上下文中的代理。

如果第2步和第3步按不同的順序通過,那麼你沒有問題。

我不知道如何控制註釋的處理順序。我甚至不確定這是可能的。

基本上有兩個解決方案

  1. 使用不同種類的魔法來處理@Transaction。默認的方法是創建代理對象,但可以指示Spring來檢測當前類。
  2. 將其拆分爲兩個類別,每個類別只有一個註釋的方法。

例子:

@Service 
public class UserServiceImpl implements UserService { 

    @Override 
    @Transactional 
    public void doSomething() { 

    } 
} 

@Service 
public class UserServiceScheduler { 

    @Inject 
    private UserService service; 

    @Scheduled(fixedRateString = "${somestring}",initialDelayString = "${anotherstring}") 
    public void doSomething() { 
     service.doSomething(); 
    } 
} 

我個人推薦第二種方法。

+0

我知道這個解決方案,它的工作原理。但是我也想知道爲什麼Spring有這樣的行爲? –

+0

@АртёмСайданов我添加了一些解釋。有關'@ Transactional'如何工作的更多細節,您可以在互聯網上輕鬆找到。 – talex

相關問題