为什么@Scheduled注释不适用于@Transaction注释。 春季启动

我有一个问题:为什么当我们使用@Scheduled@Transaction注释方法时,事务不起作用? 我知道@Scheduled调用我的类而不是Spring创建的代理类,但无法理解这种行为。

 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() { } } 

我有两个解决这个问题的方法:

  1. Scheduled方法调用代理。

  2. 实现ConcurrentTaskScheduler并将ScheduledMethodRunnable (即我的类)的对象替换为带有代理的ScheduledMethodRunnable对象。

但是这种解决方案非常不方便。

你能解释一下为什么@Scheduled这样吗?

谢谢!

这是因为要处理两个注释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(); } } 

我个人推荐第二种方法。