为什么@Scheduled注释不能与@Transaction注释一起使用.春季靴
我有一个问题:
为什么当我们用@Scheduled
和@Transaction
注释方法时,事务不起作用?
我知道@Scheduled
调用我的类,而不是Spring创建的代理类,但是无法理解这种行为.
I have a question:
Why when we annotate method with @Scheduled
and @Transaction
, transaction doesn't work?
I know that the @Scheduled
call my class instead of proxy class that created by Spring, but can't understand this behavior.
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() {
}
}
我对此问题有两种解决方案:
I have two solutions of this problem:
-
从
Scheduled
方法调用代理.
实施ConcurrentTaskScheduler
并替换ScheduledMethodRunnable
的对象(与我的课程相同)
带有ScheduledMethodRunnable
对象和代理.
Implement ConcurrentTaskScheduler
and replace object of ScheduledMethodRunnable
(that is with my class)
with object of ScheduledMethodRunnable
with proxy.
但是这种解决方案非常不方便.
But this solutions is very inconvenient.
您能解释为什么@Scheduled
如此工作吗?
Can you explaim me why @Scheduled
works like this?
谢谢!
发生这种情况是因为要同时处理两个注释,并且使用了MAGIC.
It happens because to process both annotations MAGIC is used.
我想发生了几件事:
-
UserServiceImpl
已创建.
处理 -
@Scheduled
批注,并存储对bean的引用以在适当的时候调用它. -
@Transactional
批注已处理.它创建代理,该代理存储对原始bean的引用.原始bean被替换为应用程序上下文中的代理.
-
UserServiceImpl
is created. -
@Scheduled
annotation is processed and reference to bean is stored to invoke it at appropriate time. -
@Transactional
annotation is processed. It create proxy which store reference to original bean. Original bean is replaced to proxy in application context.
如果第2步和第3步以不同的顺序通过,那么您就没问题了.
If step 2 and 3 passed in different order then you had no problem.
我不知道如何控制注释的处理顺序.我什至不知道有没有可能.
I don't know how to control order in which annotation is processed. I don't even sure it is possible at all.
基本上有两个解决方案.
- 使用另一种魔法来处理
@Transaction
.默认方法是创建代理对象,但可以指示Spring
检测当前类. - 将其拆分为两个类,每个类都将具有仅带有一个注释的方法.
- Use different kind of magic to process
@Transaction
. Default way is to create proxy object, but it is possible to instructSpring
to instrument current class. - Split this to two class each of them will have method with only one annotation.
示例:
@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();
}
}
我个人建议第二种方法.
I'm personally recommend second approach.