1

Spring事务管理可以通过@EnableTransactionManagement注解开启,通过对@EnableTransactionManagement的分析,就能揭开Spring启用事务的底层机制。

直接开始源码分析。

@EnableTransactionManagement注解作用在配置类上,引入了TransactionManagementConfigurationSelector,这个先放一放,后面再分析。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {

我们先看一下他定义的方法:

boolean proxyTargetClass() default false;
AdviceMode mode() default AdviceMode.PROXY;
int order() default Ordered.LOWEST_PRECEDENCE;

定义了3个方法,我们逐个分析一下:

  1. proxyTargetClass

    boolean proxyTargetClass() default false;

Indicate whether subclass-based (CGLIB) proxies are to be created (true) as opposed to standard Java interface-based proxies (false). The default is false. Applicable only if mode() is set to AdviceMode.PROXY.
Note that setting this attribute to true will affect all Spring-managed beans requiring proxying, not just those marked with @Transactional. For example, other beans marked with Spring's @Async annotation will be upgraded to subclass proxying at the same time. This approach has no negative impact in practice unless one is explicitly expecting one type of proxy vs another, e.g. in tests.

决定采用CGLIB的方式(设置为TRUE)、还是JDK方式创建代理类(设置为false),默认值为false。仅在Mode设置为PROXY的情况下才有效。
需要注意的是设置为true后会影响所有的的被Spring管理的代理类的创建方式,不止是@Transactional注解标注的类。比如,其他的被@Async标注的类也会被影响。

大概意思是说,在Mode设置为PROXY的情况下,这个参数决定代理类的创建方式,设置为true则通过CGLIB方式创建代理对象,设置为false则通过JDK方式创建代理对象。默认是通过JDK方式创建。

但是为什么设置为true后会影响到不止是@Transactional注解标注的类,而是会影响到整个Spring管理的bean呢?待考证。

  1. mode

    AdviceMode mode() default AdviceMode.PROXY;
    Indicate how transactional advice should be applied.
    The default is AdviceMode.PROXY. Please note that proxy mode allows for interception of calls through the proxy only. Local calls within the same class cannot get intercepted that way; an Transactional annotation on such a method within a local call will be ignored since Spring's interceptor does not even kick in for such a runtime scenario. For a more advanced mode of interception, consider switching this to AdviceMode.ASPECTJ.
    事务advice(AOP概念)的实现方式,默认值为PXOXY,注意PROXY模式只允许通过代理方式调用,本地调用不生效。事务注解方法如果通过本地调用的话,事务处理不会生效,因为这种情况下Spring AOP的拦截机制不会生效。

JavaDoc说的很明白了,也是我们在其他文章里面提到过的,如果在同一个类中一个方法A调用被@Transactional标注的另外一个方法B的话,方法B的@Transactional不会生效,因为这种情况下的调用就属于这里所说的“本地调用”,没有调用到代理类,AOP拦截机制不会生效,因此方法B不会被AOP增强,因此事务不会生效。

  1. Ordered
    很熟悉的AOP增强概念,当多个拦截器生效的情况下,决定其顺序。

    int order() default Ordered.LOWEST_PRECEDENCE;

好了,今天就到这里,由于Spring源码本身比较复杂,一次分析太多、文章太大的话,会比较乱,所以,改变一下思路,一篇文章只说一个概念,控制文章的篇幅,增强可读性。

上一篇 Spring事务框架之TransactionManager(4)
下一篇 启用Spring事务管理@EnableTransactionManagement(2)


45 声望17 粉丝