@Transactional with static method

前端 未结 3 1481
长情又很酷
长情又很酷 2020-12-19 08:07

Why cant we use @Transactional for static methods to manage the transactions in my spring Project ?

@Transactional works well for non stati

相关标签:
3条回答
  • 2020-12-19 08:48

    In order to understand why something like what you are proposing does not work you have to first understand at a high level how Spring handles beans that use @Transactional.

    When you annotate a method or the class as @Transactional and make it a Spring Bean, Spring effectively creates a proxy for that class (using JDK Dynamic proxies or CGLIB proxies). That means that whenever your class is used (from Spring managed code that is), it's not your code that gets called immediately, but the proxy which first does whatever is needed, and then your code is called (in the case of caching support your code would perhaps not even be called at all). A key thing to remember here is that the invoking code (the call site if you will) does not change at all, and the invocation of to the required target method (the proxy method) is performed by the JVM using the same bytecode (invokevirtual or invokeinterface).

    With that in mind, the reason that static is not supported becomes clear. You can't create a proxy for static method! Of course Java Dynamic Proxies cannot do this, and neither can CGLIB.

    Supporting such a feature would require changing the bytecode of the invoking code, since calling a static method is implemented via invokestatic in bytecode, which hard-codes the target method.

    This part of the Spring documentation explains Spring AOP in details

    0 讨论(0)
  • 2020-12-19 08:49

    If you're using AspectJ, here's a simple, albeit ugly, workaround:

    public static void doWhatever(final String param) {
        new Runnable() {
            @Transactional
            public void run() {
                // do whatever in transaction...
            }
        }.run();
    }
    
    0 讨论(0)
  • 2020-12-19 08:49

    This is feasible using:

    1. @EnableTransactionManagement(mode = ASPECTJ) (or its XML equivalent)
    2. all the configuration required to make AspectJ work
    3. registering a custom aspect to handle @Transactional over static methods like this one I just stumbled upon (did not test it)

    NB: in this post I asked about how to make package-private methods @Transactional.

    0 讨论(0)
提交回复
热议问题