我有一个问题:
为什么当我们使用@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
会这样运作吗?
谢谢!
答案 0 :(得分:1)
之所以发生这种情况,是因为要处理两个注释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();
}
}
我个人推荐第二种方法。
答案 1 :(得分:0)
问题不是私有的还是公共的,问题是:如何调用它以及您使用哪种AOP实现!
如果使用(默认)Spring Proxy AOP,则仅当调用通过代理时,才会考虑Spring提供的所有AOP功能(例如@Transational
)。 -如果从另一个 bean调用带注释的方法,通常是这种情况。
这有两个含义:
@Transactional
注释。您也可以使用AspectJ模式代替Spring Proxies,它将克服此问题。而且AspectJ事务性方面甚至被编织成私有方法(已在Spring 3.0中进行了检查)。