@Transactional用静态方法

时间:2014-05-09 16:33:04

标签: spring transactions

为什么我们不能使用@Transactional静态方法来管理我的Spring项目中的事务?

@Transactional适用于非静态方法但不适用于静态方法的任何特定原因?

3 个答案:

答案 0 :(得分:10)

为了理解为什么你提出的建议不起作用,你必须首先从高层次上理解Spring如何处理使用@Transactional的bean。

当您将方法或类注释为@Transactional并使其成为Spring Bean时,Spring会有效地为该类创建代理(使用JDK动态代理或CGLIB代理)。这意味着无论何时使用您的类(来自Spring托管代码),都不会立即调用您的代码,而是首先执行所需操作的代理,然后调用您的代码(在缓存支持的情况下)甚至可能根本不会调用代码。 这里需要记住的一件重要事情是,调用代码(如果你愿意,调用站点)根本不会改变,并且JVM使用相同的字节码执行对所需目标方法(代理方法)的调用(< em> invokevirtual 或 invokeinterface )。

考虑到这一点,不支持静态的原因变得清晰。 您无法为静态方法创建代理!当然Java Dynamic Proxies不能这样做,CGLIB也不能。

支持这样的功能需要更改调用代码的字节码,因为调用静态方法是通过字节码中的invokestatic实现的,它对目标方法进行了硬编码。

This部分Spring文档详细解释了Spring AOP

答案 1 :(得分:1)

如果你正在使用AspectJ,这里有一个简单的,虽然很丑陋的解决方法:

public static void doWhatever(final String param) {
    new Runnable() {
        @Transactional
        public void run() {
            // do whatever in transaction...
        }
    }.run();
}

答案 2 :(得分:0)

这是可行的:

  1. @EnableTransactionManagement(mode = ASPECTJ)(或其XML等价物)
  2. 使AspectJ工作所需的所有配置
  3. 注册自定义方面以处理@Transactional静态方法,例如this one我偶然发现(未测试)
  4. 注意:在this post中,我询问了如何制作包私有方法@Transactional