为什么@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() { } }
我有两个解决这个问题的方法:
-
从
Scheduled
方法调用代理。 -
实现
ConcurrentTaskScheduler
并将ScheduledMethodRunnable
(即我的类)的对象替换为带有代理的ScheduledMethodRunnable
对象。
但是这种解决方案非常不方便。
你能解释一下为什么@Scheduled
这样吗?
谢谢!
这是因为要处理两个注释MAGIC。
我想有几件事情发生了:
-
UserServiceImpl
已创建。 - 处理
@Scheduled
注释并存储对bean的引用以在适当的时候调用它。 - 处理
@Transactional
注释。 它创建代理,存储对原始bean的引用。 原始bean在应用程序上下文中替换为代理。
如果步骤2和3以不同的顺序通过,那么你没有问题。
我不知道如何控制处理注释的顺序。 我甚至不确定它是否可行。
基本上有两个解决方案 。
- 使用不同类型的魔法来处理
@Transaction
。 默认方式是创建代理对象,但可以指示Spring
对当前类进行检测。 - 将其拆分为两个类,每个类都将只有一个注释的方法。
例:
@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(); } }
我个人推荐第二种方法。