2017-07-27 438 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

相关问题