在我的理解中,以下代码中的newPrint
方法应该创建一个新事务,但显然它打印出与oldPrint
方法中使用的相同的事务状态对象。我从另一个班级打电话给oldPrint。是因为使用this
调用newPrint吗?如果是,那么什么时候会创建新的交易?如果我从另一个类调用这两个方法,则无论如何都会创建两个单独的事务,因为在类级别使用了@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
可行的情况是什么?
答案 0 :(得分:1)
假设geoand的编辑说明是正确的,那么您的问题的答案是Spring使用AOP代理来应用事务限制。因此,当来自外部的调用进入您的Unsubscriber时,这将会起作用,然后可以截取它并且可以应用事务边界。如果您正在课堂上调用它,正如您所说,使用'这个',那么就没有代理可以完成,因此您的@Transactional将无法发挥作用。
答案 1 :(得分:1)
以下是一些值得一提的@Transactional规则
1. @ Transactional注释仅适用于公共方法。如果你有一个私有或受保护的方法与这个注释没有(容易) Spring AOP查看注释的方法。尝试并不疯狂 找到它们,以确保所有注释方法都是公开的。
2.只有在通过Spring代理调用正确注释(见上文)方法时才会创建事务边界。这意味着 你需要通过@Autowired直接调用带注释的方法 bean或事务永远不会启动。如果你在一个方法上调用一个方法 @Autowired bean没有注释,它本身称为公共 注释的方法您的注释被忽略。这是因为 Spring AOP仅在首次进入注释时检查注释 @Autowired代码。
来源 - http://blog.timmattison.com/archives/2012/04/19/tips-for-debugging-springs-transactional-annotation/
答案 2 :(得分:0)
你所看到的是关于Spring AOP的阶级误解。
由于从同一个类内的方法调用newPrint()
,因此不会触发任何建议,因此不会对事务进行处理。
如果你在课堂外调用方法newPrint()
,无论调用者是否已经参与交易,都会创建一个新的交易。
由于您在课程中使用了@Transactional
,因此每个方法都是默认的@Transactional
设置,这就是您实际进行交易的原因。
查看Spring参考文档的this部分,详细讨论AOP如何在Spring中工作。
让代码按预期运行的完全黑客攻击如下:
((Unsubcriber ) AopContext.currentProxy()).newPrint();
此解决方案在各个地方都有提及,其中this SO post。
答案 3 :(得分:0)
从类中调用方法(使用this
)意味着它不会经历Spring的代理对象中包含的事务初始化。由于this
关键字是指向原始对象实例的指针,而不是事务感知的增强型Spring对象。
注释将在以下场景中按预期工作:
object1.oldPrint();
object1.newPrint();