Spring @使用静态方法进行事务处理

Spring @使用静态方法进行事务处理,spring,transactions,Spring,Transactions,为什么我们不能使用@Transactional作为静态方法来管理我的spring项目中的事务 @Transactional适用于非静态方法,但不适用于静态方法任何特定原因 为了理解为什么像您建议的那样的东西不起作用,您必须首先从较高的层次了解Spring如何处理使用@Transactional的bean 当您将方法或类注释为@Transactional并使其成为Springbean时,Spring会有效地为该类创建一个代理(使用JDK动态代理或CGLIB代理)。这意味着,无论何时使用您的类(即S

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


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

为了理解为什么像您建议的那样的东西不起作用,您必须首先从较高的层次了解Spring如何处理使用
@Transactional
的bean

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

记住这一点,静态不受支持的原因就变得很清楚了。 无法为静态方法创建代理!当然,Java动态代理不能做到这一点,CGLIB也不能

支持这种特性需要更改调用代码的字节码,因为调用静态方法是通过字节码中的invokestatic实现的,后者硬编码目标方法


Spring文档的一部分详细解释了Spring AOP,这可以使用:

  • @EnableTransactionManagement(mode=ASPECTJ)
    (或其XML等价物)
  • 使AspectJ工作所需的所有配置
  • 在静态方法上注册一个自定义方面来处理
    @Transactional
    ,就像我刚刚偶然发现的那样(没有测试它)

  • 注意:在中,我询问了如果您使用的是AspectJ,如何使包私有方法
    @Transactional

    ,这里有一个简单但难看的解决方法:

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

    因为它不受支持。我知道它不受支持,但有任何特定的原因使它不受支持…我搜索了这个,看起来cglib无法创建
    静态
    方法。cglib是Spring用来动态创建代理的库。okie..我知道你已经解释过了…使用一些静态代理模式为静态方法创建代理是否困难?或者我们根本不能为静态方法创建代理,如果不是为什么的话?当调用静态方法时,没有类的对象,因此没有任何东西可以代替它,这意味着不能使用代理。我能想到的唯一可行的方法是改变字节码,但我不知道这是否可行