Spring Propagation.REQUIRES_NEW

时间:2014-04-29 12:23:33

标签: java spring-transactions

在我的理解中,以下代码中的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可行的情况是什么?

4 个答案:

答案 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();