Spring 事务源码(3)—@EnableTransactionManagement事务注解源码解析

  基于最新Spring 5.x,详细介绍了Spring 事务源码,包括@EnableTransactionManagement事务注解源码解析

  上一篇文章:Spring 事务源码(2)—<tx:annotation-driven/>事务标签源码解析中我们讲解了<tx:annotation-driven/>标签的解析源码,现在我们来看看用于替代该标签的注解@EnableTransactionManagement事务注解的源码解析。

Spring 事务源码 系列文章

Spring 5.x 源码汇总

Spring 事务源码(1)—<tx:advice/>事务标签源码解析

Spring 事务源码(2)—<tx:annotation-driven/>事务标签源码解析

Spring 事务源码(3)—@EnableTransactionManagement事务注解源码解析

Spring 事务源码(4)—BeanFactoryTransactionAttributeSourceAdvisor注解事务通知器源码解析

Spring 事务源码(5)—TransactionInterceptor事务拦截器与事务的AOP增强实现

Spring 事务源码(6)—createTransactionIfNecessary处理事务属性并尝试创建事务【两万字】

Spring 事务源码(7)—事务的completeTransactionAfterThrowing回滚、commitTransactionAfterReturning提交以及事务源码总结【一万字】

1 @EnableTransactionManagement源码入口

  @EnableTransactionManagement注解用于替代<tx:annotation-driven/>标签来开启声明式事务注解驱动!它是@Eenable开头的注解,这实际上就很简单了,我们在此前异步任务的源码:Spring @Async异步任务源码(1)—<task:annotation-driven/>、<task:executor/>、@EnableAsync解析的文章中@EnableAsync注解解析的部分就讲过,这样的注解的关键通常是内部的@Import元注解,@Import注解用于引入bean到容器中!

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
//核心注解
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {

    /**
     * 指示是否创建基于子类(CGLIB)的代理,而不是标准的基于Java接口的代理(false)。默认为false,即基于Java接口。
     * 仅当mode()设置为AdviceMode.PROXY时适用。
     */
    boolean proxyTargetClass() default false;

    /**
     * 指示应该如何应用事务性通知。
     * <p>
     * 默认为AdviceMode.PROXY,即基于Spring AOP动态代理。请注意,代理模式只允许通过代理拦截调用。
     * 同一个类中的本地方法互相调用中,被调用方法上的事务注解将被忽略,因为Spring的拦截器不会在这样的运行时场景中发挥作用。
     * 对于更高级的拦截模式,考虑将其切换到AdviceMode.ASPECTJ,即以及Aspect的静态织入
     */
    AdviceMode mode() default AdviceMode.PROXY;

    /**
     * 指示在特定连接点应用多个通知时事务通知器的执行顺序。
     * <p>
     * 默认为Ordered.LOWEST_PRECEDENCE
     */
    int order() default Ordered.LOWEST_PRECEDENCE;

}

2 TransactionManagementConfigurationSelector

  @Import注解引入的Class的类型不同,将会执行不同的解析流程,这一点我们在此前异步任务的源码中的@EnableAsync注解解析的部分也讲过了。@EnableTransactionManagement内部的@Import元注解指定的是TransactionManagementConfigurationSelector.class,这个类是一个ImportSelectorBean,因此我们直接看这个类的selectImports方法即可!
  TransactionManagementConfigurationSelector还继承了AdviceModeImportSelector,这是一个通用的基类,该基类及其实现类将会根据AdviceMode选择导入不同的注册的bean!这些特征说明TransactionManagementConfigurationSelector和@EnableAsync注解内部的@Import注解指定的AsyncConfigurationSelector.class属于同一体系。
  通常情况下,selectImports方法将会返回org.springframework.context.annotation.AutoProxyRegistrar和org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration这两个class,即将会注册这两个bean定义到容器中。

/**
 * 这是一个通用基类,用于根据AdviceMode来选择注册不同的bean定义,该基类被用于广泛的支持@Enable*注解
 * 比如@EnableAsync、@EnableCaching、@EnableTransactionManagement(需要spring-tx依赖)
 *
 * @param <A> 注解类型泛型
 */
public abstract class AdviceModeImportSelector<A extends Annotation> implements ImportSelector {

    /**
     * AdviceMode属性的默认属性名字为"mode"
     */
    public static final String DEFAULT_ADVICE_MODE_ATTRIBUTE_NAME = "mode";


    /**
     * 获取AdviceMode属性的属性名,默认为"mode",子类可以覆盖重写
     */
    protected String getAdviceModeAttributeName() {
        return DEFAULT_ADVICE_MODE_ATTRIBUTE_NAME;
    }

    /**
     * 该方法就是核心方法,在解析@Import注解时就会自动调用
     * <p>
     * 该方法首先会校验指定的注解中是否存在类型为AdviceMode名字为getAdviceModeAttributeName()返回值的属性
     * 然后会调用另一个selectImports(AdviceMode adviceMode)方法,该方法被子类重写,用于根据mode值判断应该使用哪些bean
     */
    @Override
    public final String[] selectImports(AnnotationMetadata importingClassMetadata) {
        //获取确定的泛型类型
        Class<?> annType = GenericTypeResolver.resolveTypeArgument(getClass(), AdviceModeImportSelector.class);
        Assert.state(annType != null, "Unresolvable type argument for AdviceModeImportSelector");
        //获取该泛型注解的属性集合
        AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
        if (attributes == null) {
            throw new IllegalArgumentException(String.format(
                    "@%s is not present on importing class '%s' as expected",
                    annType.getSimpleName(), importingClassMetadata.getClassName()));
        }
        //从属性集合中根据AdviceMode属性的属性名获取属性值
        AdviceMode adviceMode = attributes.getEnum(getAdviceModeAttributeName());
        //调用selectImports(AdviceMode adviceMode)方法选择合适bean,该方法被子类重写
        String[] imports = selectImports(adviceMode);
        //不能为null
        if (imports == null) {
            throw new IllegalArgumentException("Unknown AdviceMode: " + adviceMode);
        }
        return imports;
    }

    /**
     * 根据给定的AdviceMode确定应导入哪些类,该方法应被子类重写
     * <p>
     * 返回null将会抛出IllegalArgumentException异常.
     */
    @Nullable
    protected abstract String[] selectImports(AdviceMode adviceMode);

}

/**
 * 子类实现了AdviceModeImportSelector,泛型类型为@EnableTransactionManagement注解
 * 重写了selectImports(AdviceMode adviceMode)方法
 */
public class TransactionManagementConfigurationSelector extends org.springframework.context.annotation.AdviceModeImportSelector<org.springframework.transaction.annotation.EnableTransactionManagement> {

    /**
     * 如果EnableAsync#mode是PROXY,那么返回AutoProxyRegistrar和ProxyTransactionManagementConfiguration
     * 如果EnableAsync#mode是ASPECTJ,那么返回AspectJ(Jta)TransactionManagementConfiguration
     */
    @Override
    protected String[] selectImports(AdviceMode adviceMode) {
        switch (adviceMode) {
            case PROXY:
                //一般都是PROXY,因此将会注册AutoProxyRegistrar和ProxyTransactionManagementConfiguration的bean定义,进行动态代理
                return new String[]{AutoProxyRegistrar.class.getName(),
                        ProxyTransactionManagementConfiguration.class.getName()};
            case ASPECTJ:
                //支持Aspectj的静态代理织入
                return new String[]{determineTransactionAspectClass()};
            default:
                //其他值则返回null,将会抛出异常
                return null;
        }
    }

    private String determineTransactionAspectClass() {
        return (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader()) ?
                TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME :
                TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME);
    }

}

2.1 AutoProxyRegistrar注册自动代理创建者

  AutoProxyRegistrar属于ImportBeanDefinitionRegistrar类型,因此它本身实际上并不会注册到容器中,而是会调用它的registerBeanDefinitions方法,该方法中会尝试注册一个InfrastructureAdvisorAutoProxyCreator自动代理创建者,用于后续创建代理对象。
  目前,只有@EnableCaching和@EnableTransactionManagement注解有可能自动引入AutoProxyRegistrar。因此在方法的第一参数将会传入具有@EnableCaching和@EnableTransactionManagement注解的类的元数据。
  另外还会解析并设置自动代理创建者的proxyTargetClass属性。因此,如果引入类上有多个符合条件的自动代理注解(比如@EnableTransactionManagement、@EnableAsync、@EnableCaching、@EnableAspectJAutoProxy),并且有某个自动代理注解的proxyTargetClass属性设置为true,那么容器中的自动代理创建者的proxyTargetClass属性将会被设置为true,表示强制使用CGLIB代理。

/**
 * AutoProxyRegistrar的方法
 * <p>
 * 尝试为自动代理注册一个InfrastructureAdvisorAutoProxyCreator类型的自动代理创建者
 * 并且会解析proxyTargetClass属性,如果有某个注解的proxyTargetClass属性设置为true
 * 那么自动代理创建者的proxyTargetClass属性将会被设置为true,表示强制使用CGLIB代理。
 *
 * @param importingClassMetadata 引入该类的类的元数据。目前,只有@EnableCaching和@EnableTransactionManagement注解有可能引入该类
 *                               因此将会传入,具有@EnableCaching和@EnableTransactionManagement注解的类的元数据
 * @param registry               bean定义注册表
 */
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    boolean candidateFound = false;
    //获取类上的所有注解类型
    Set<String> annTypes = importingClassMetadata.getAnnotationTypes();
    //循环处理,对于具有mode和proxyTargetClass属性的注解统一处理
    for (String annType : annTypes) {
        //每一个注解的属性集合
        AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
        if (candidate == null) {
            continue;
        }
        //获取mode属性
        Object mode = candidate.get("mode");
        //获取proxyTargetClass属性
        Object proxyTargetClass = candidate.get("proxyTargetClass");
        /*
         * 如果存在这两个属性,并且类型也是匹配的
         * 很多注解都有这两个属性,比如@EnableTransactionManagement、@EnableAsync、@EnableCaching、@EnableAspectJAutoProxy
         */
        if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
                Boolean.class == proxyTargetClass.getClass()) {
            //
            candidateFound = true;
            //如果mode值是AdviceMode.PROXY值
            if (mode == AdviceMode.PROXY) {
                /*
                 * 调用AopConfigUtils.registerAutoProxyCreatorIfNecessary方法
                 * 尝试注册或者升级一个名为"org.springframework.aop.config.internalAutoProxyCreator"
                 * 类型为InfrastructureAdvisorAutoProxyCreator的自动代理创建者的bean定义
                 */
                AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
                /*
                 * 如果有某个注解的proxyTargetClass属性设置为true
                 * 那么自动代理创建者的proxyTargetClass属性将会被设置为true,表示强制使用CGLIB代理。
                 */
                if ((Boolean) proxyTargetClass) {
                    AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
                    return;
                }
            }
        }
    }
    if (!candidateFound && logger.isInfoEnabled()) {
        String name = getClass().getSimpleName();
        logger.info(String.format("%s was imported but no annotations were found " +
                "having both 'mode' and 'proxyTargetClass' attributes of type " +
                "AdviceMode and boolean respectively. This means that auto proxy " +
                "creator registration and configuration may not have occurred as " +
                "intended, and components may not be proxied as expected. Check to " +
                "ensure that %s has been @Import'ed on the same class where these " +
                "annotations are declared; otherwise remove the import of %s " +
                "altogether.", name, name, name));
    }
}

2.2 ProxyTransactionManagementConfiguration注册事务管理bean

  ProxyTransactionManagementConfiguration类是一个@Configuration配置类,将会通过内部的@Bean方法向容器注入一系列与AOP事务相关的一些基础bean定义,包括BeanFactoryTransactionAttributeSourceAdvisor事务通知器、AnnotationTransactionAttributeSource注解事务属性源、TransactionInterceptor事务拦截器、TransactionalEventListenerFactory事务事件监听器工厂

@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {

    /**
     * 注册一个事务通知器bean定义,名为"org.springframework.transaction.config.internalTransactionAdvisor"
     * 类型就是BeanFactoryTransactionAttributeSourceAdvisor
     *
     * @param transactionAttributeSource 事务属性源
     * @param transactionInterceptor     事务拦截器
     */
    @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
            TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {
        //创建BeanFactoryTransactionAttributeSourceAdvisor
        BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
        //设置属性源
        advisor.setTransactionAttributeSource(transactionAttributeSource);
        //设置通知
        advisor.setAdvice(transactionInterceptor);
        //设置@EnableTransactionManagement注解的order属性
        if (this.enableTx != null) {
            advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
        }
        return advisor;
    }


    /**
     * 注册一个事务属性源bean定义,名为"transactionAttributeSource"
     * 类型就是AnnotationTransactionAttributeSource
     */
    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public TransactionAttributeSource transactionAttributeSource() {
        return new AnnotationTransactionAttributeSource();
    }

    /**
     * 注册一个事务拦截器bean定义,名为"transactionAttributeSource"
     * 类型就是TransactionInterceptor
     *
     * @param transactionAttributeSource 事务属性源
     */
    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) {
        TransactionInterceptor interceptor = new TransactionInterceptor();
        interceptor.setTransactionAttributeSource(transactionAttributeSource);
        //设置事务管理器,这个事务管理器是指通过TransactionManagementConfigurer配置的,而不是通过bean定义的,一般为null
        //所以说通过注解配置的TransactionInterceptor的transactionManager一般都为null,但是没关系,在使用时如果发现为null
        //Spring会查找容器中的TransactionManager的实现来作为事务管理器
        if (this.txManager != null) {
            interceptor.setTransactionManager(this.txManager);
        }
        return interceptor;
    }

}

/**
 * 父类AbstractTransactionManagementConfiguration
 */
@Configuration
public abstract class AbstractTransactionManagementConfiguration implements ImportAware {

    @Nullable
    protected AnnotationAttributes enableTx;

    /**
     * 通过TransactionManagementConfigurer配置的默认事务管理器,可以为null
     */
    @Nullable
    protected TransactionManager txManager;

    /**
     * 自动回调方法
     * 用于获取@EnableTransactionManagement注解的属性
     *
     * @param importMetadata 引入当前类的类元数据,就是标注有@EnableTransactionManagement注解的类
     */
    @Override
    public void setImportMetadata(AnnotationMetadata importMetadata) {
        //获取引入当前配置类的类上面的@EnableTransactionManagement注解的属性
        this.enableTx = AnnotationAttributes.fromMap(
                importMetadata.getAnnotationAttributes(EnableTransactionManagement.class.getName(), false));
        //没有就抛出异常
        if (this.enableTx == null) {
            throw new IllegalArgumentException(
                    "@EnableTransactionManagement is not present on importing class " + importMetadata.getClassName());
        }
    }

    /**
     * 期望通过TransactionManagementConfigurer的方式注入事务管理器
     * 由于@Autowired的required属性为false,没有TransactionManagementConfigurer的bean的时候,将不会执行该方法
     */
    @Autowired(required = false)
    void setConfigurers(Collection<TransactionManagementConfigurer> configurers) {
        //没有就返回
        if (CollectionUtils.isEmpty(configurers)) {
            return;
        }
        //超过一个事务管理器配置类就抛出异常
        if (configurers.size() > 1) {
            throw new IllegalStateException("Only one TransactionManagementConfigurer may exist");
        }
        //从事务管理器配置类中获取事务管理器
        TransactionManagementConfigurer configurer = configurers.iterator().next();
        this.txManager = configurer.annotationDrivenTransactionManager();
    }


    /**
     * 注册一个事务事件监听器工厂的bean定义,名为"org.springframework.transaction.config.internalTransactionalEventListenerFactory"
     * 类型就是TransactionalEventListenerFactory
     * <p>
     * 该工厂可以将@TransactionalEventListener注解方法解析为一个ApplicationListenerMethodTransactionalAdapter类型的事件监听器,用于支持事务事件的监听。
     */
    @Bean(name = TransactionManagementConfigUtils.TRANSACTIONAL_EVENT_LISTENER_FACTORY_BEAN_NAME)
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public static TransactionalEventListenerFactory transactionalEventListenerFactory() {
        return new TransactionalEventListenerFactory();
    }
}

3 小结

  @EnableTransactionManagement注解用于开启注解事务支持,也就是说如果配置了该注解,那么可以使用基于注解的声明式事务!
  从源码中能看出,该标签会:

  1. @EnableTransactionManagement注解的关键在于内部的@Import注解,该注解尝试向容器注入AutoProxyRegistrar和ProxyTransactionManagementConfiguration两个bean。
  2. AutoProxyRegistrar会尝试注册一个名为org.springframework.aop.config.internalAutoProxyCreator的InfrastructureAdvisorAutoProxyCreator类型的自动代理创建者的bean定义,该bean用于创建代理对象。
    1. 另外还会解析并设置自动代理创建者的proxyTargetClass属性。如果引入类上有多个符合条件的自动代理注解(比如@EnableTransactionManagement、@EnableAsync、@EnableCaching、@EnableAspectJAutoProxy),并且有某个自动代理注解的proxyTargetClass属性设置为true,那么容器中的自动代理创建者的proxyTargetClass属性将会被设置为true,表示强制使用CGLIB代理。
  3. ProxyTransactionManagementConfiguration会尝试配置AOP事务相关的一些基础bean定义,包括BeanFactoryTransactionAttributeSourceAdvisor事务通知器、AnnotationTransactionAttributeSource注解事务属性源、TransactionInterceptor事务拦截器、TransactionalEventListenerFactory事务事件监听器工厂!

  总体来说,源码比较简单!如果和前一篇文章Spring 事务源码(2)—<tx:annotation-driven/>事务标签源码解析的内容进行对比,我们发现它们所做的事都是差不多的,都会尝试注册那些基础bean,这些bean被用于后续Spring 事务的处理逻辑中,我们后面会一一讲到。因此,我们可以说,@EnableTransactionManagement可用于替代<tx:annotation-driven/>标签。

相关文章:
  https://spring.io/
  Spring Framework 5.x 学习
  Spring Framework 5.x 源码

如有需要交流,或者文章有误,请直接留言。另外希望点赞、收藏、关注,我将不间断更新各种Java学习博客!

  • 8
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刘Java

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值