我有一个问题:为什么当我们用@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
会这样工作吗?
谢谢!
发布于 2017-07-27 16:18:54
之所以会发生这种情况,是因为为了处理这两个注释,都使用了魔术。
我想有几件事发生了:
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();
}
}
我个人推荐第二种方法。
发布于 2019-01-30 15:50:22
问题不是私有的,也不是公开的,问题是:它是如何被调用的,以及您使用的是哪个AOP实现!
如果您使用(默认) Spring,那么Spring提供的所有AOP功能(如@Transational
)只有在调用通过代理时才会被考虑。--如果从(另一个 bean )调用带注释的方法,则通常是这种情况。
这有两个含义:
@Transactional
注释。您还可以使用aspectJ模式,而不是Spring代理,这将解决问题。AspectJ事务方面甚至被编织到私有方法中(Spring3.0检查)。
参考:http://docs.spring.io/spring/docs/3.2.4.RELEASE/spring-framework-reference/html/aop.html#aop-proxying
https://stackoverflow.com/questions/45355601
复制相似问题