根据我的理解,下面的代码中的newPrint方法应该创建一个新的事务,但显然它打印出了与oldPrint方法中使用的事务状态对象相同的事务状态对象。我从另一个班给oldPrint打电话。是因为newPrint是使用this调用的吗?如果是,那么什么时候会创建一个新事务?如果我从另一个类调用两个方法,那么无论如何都会创建两个单独的事务,因为@Transactional是在类级别上使用的。
@Transactional
public class Unsubcriber {
@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
public void newPrint() {
System.out.println(TransactionAspectSupport.currentTransactionStatus());
}
public void oldPrint() {
System.out.println(TransactionAspectSupport.currentTransactionStatus());
newPrint();
}输出:
org.springframework.transaction.support.DefaultTransactionStatus@3bacd0e7
org.springframework.transaction.support.DefaultTransactionStatus@3bacd0e7当Propagation.REQUIRES_NEW起作用时,会发生什么情况呢?
发布于 2014-04-29 12:30:34
您所看到的是关于Spring的类误解。
由于newPrint()是从同一个类中的方法调用的,因此不会触发任何通知,因此不会对事务进行任何处理。
如果在类之外调用方法newPrint(),则将创建一个新事务,无论调用方是否已经参与了事务。
由于您已经在类中使用了@Transactional,所以每个方法都是默认的@Transactional设置,这就是您实际拥有事务的原因。
查看Spring参考文档中的这部分,详细讨论AOP在Spring中的工作方式。
要使您的代码像您预期的那样工作,一次完全的黑客攻击将如下所示:
((Unsubcriber ) AopContext.currentProxy()).newPrint();这个解决方案在很多地方都有提到,其中包括这所以post。
发布于 2014-04-29 12:32:08
假设geoand的编辑澄清是正确的,那么您的问题的答案是Spring使用AOP代理来应用事务限制。因此,这将工作时,您从外部进入取消订户,然后可以被拦截和事务边界可以应用。如果您在类中调用它,正如您所说的,使用“this”,那么就没有可以执行的代理,因此您的@Transactional就不会起作用了。
发布于 2014-04-29 12:32:36
以下是几条值得提及的“交易规则”
1.@Transactional注释只适用于公共方法。如果您有这个注释的私有或受保护的方法,那么Spring没有(容易)的方法来查看注释。寻找它们并不疯狂,所以确保所有带注释的方法都是公开的。 2.只有在通过Spring代理调用适当注释的方法(参见上文)时,才会创建事务边界。这意味着您需要直接通过@Au牛毛bean调用带注释的方法,否则事务将永远不会启动。如果您调用了一个未被注释的@Autowired上的方法,而这个方法本身调用了一个注释的公共方法,那么您的注释就会被忽略。这是因为Spring只在它第一次输入@Autowired代码时才检查注释。
源- http://blog.timmattison.com/archives/2012/04/19/tips-for-debugging-springs-transactional-annotation/
https://stackoverflow.com/questions/23364572
复制相似问题