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

  基于最新Spring 5.x,详细介绍了Spring 事务源码,包括< tx:annotation-driven/>标签源码解析。

  此前我们已经学习了Spring的<tx:advice/>事务标签源码解析:Spring 事务源码(1)—<tx:advice/>事务标签源码解析。现在我们来学习<tx:annotation-driven/>事务标签的解析源码。
  <tx:annotation-driven/>标签用于开启注解事务支持,也就是说如果配置了该标签,那么可以使用基于注解的声明式事务!
  <tx:annotation-driven/>标签由org.springframework.transaction.config.AnnotationDrivenBeanDefinitionParser这个解析器来单独解析,该解析器的uml类图如下,比较简单:
在这里插入图片描述
  同样,我们主要看它的parse方法!

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 parse解析< tx:annotation-driven/>标签

  解析<tx:annotation-driven/>标签。将在必要时调用AopNamespaceUtils#registerAutoProxyCreatorIfNecessary方法,尝试向容器中注册一个InfrastructureAdvisorAutoProxyCreator类型的bean定义。

/**
 * AnnotationDrivenBeanDefinitionParser的方法
 * <p>
 * 解析<tx:annotation-driven/>标签
 * 将在必要时调用AopNamespaceUtils#registerAutoProxyCreatorIfNecessary方法
 * 尝试向容器中注册一个InfrastructureAdvisorAutoProxyCreator类型的AutoProxyCreator。
 */
@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
    /*
     * 注册事务事件监听器工厂TransactionalEventListenerFactory的bean定义
     * 用于解析@TransactionalEventListener注解方法为一个ApplicationListenerMethodTransactionalAdapter监听器
     */
    registerTransactionalEventListenerFactory(parserContext);
    //获取<tx:annotation-driven/>标签的mode属性
    //该属性用于指示应该采用Spring AOP来对异步方法进行动态代理,还是采用AspectJ来进行静态织入
    //默认为proxy,即Spring AOP代理,如果设置为aspectj,那么还需要spring-aspects.jar(其内部包含了aspectjweaver依赖)。
    String mode = element.getAttribute("mode");
    //aspectj的mode处理,一般不需要考虑
    if ("aspectj".equals(mode)) {
        // mode="aspectj"
        registerTransactionAspect(element, parserContext);
        if (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader())) {
            registerJtaTransactionAspect(element, parserContext);
        }
    } else {
        // mode="proxy"
        //正常情况下的逻辑
        //尝试注册一个InfrastructureAdvisorAutoProxyCreator类型的自动代理创建者
        //并且配置AOP事务相关的一些基础bean定义,比如事务通知器、事务拦截器、事务属性源
        AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);
    }
    return null;
}

1.1 registerTransactionalEventListenerFactory注册事务事件监听器工厂

  注册TransactionalEventListenerFactory的bean定义,名为“org.springframework.transaction.config.internalTransactionalEventListenerFactory”。该工厂可以将@TransactionalEventListener注解方法解析为一个ApplicationListenerMethodTransactionalAdapter类型的事件监听器,用于支持事务事件的监听。

/**
 1. AnnotationDrivenBeanDefinitionParser的方法
 2. <p>
 3. 注册TransactionalEventListenerFactory的bean定义
 */
private void registerTransactionalEventListenerFactory(ParserContext parserContext) {
    //创建bean定义
    RootBeanDefinition def = new RootBeanDefinition();
    //设置为TransactionalEventListenerFactory类型
    def.setBeanClass(TransactionalEventListenerFactory.class);
    //注册bean定义到beanFactory中,beanName为"org.springframework.transaction.config.internalTransactionalEventListenerFactory"
    parserContext.registerBeanComponent(new BeanComponentDefinition(def,
            TransactionManagementConfigUtils.TRANSACTIONAL_EVENT_LISTENER_FACTORY_BEAN_NAME));
}

1.2 configureAutoProxyCreator配置自动代理创建者

  configureAutoProxyCreator方法是内部类AopAutoProxyConfigurer的方法,该方法有两个目的:

  1. 尝试注册一个InfrastructureAdvisorAutoProxyCreator类型的自动代理创建者,用于创建代理对象。
  2. 配置AOP事务相关的一些基础bean定义,比如配置BeanFactoryTransactionAttributeSourceAdvisor事务通知器、AnnotationTransactionAttributeSource注解事务属性源、TransactionInterceptor事务拦截器等。

  事务通知器的beanName为org.springframework.transaction.config.internalTransactionAdvisor,并且全局只有一个,只有当容器中不存在该bean时才会继续解析当前<tx:annotation-driven/>标签。因此,即使配置文件中存在多个<tx:annotation-driven/>标签,仍然只会有一个标签的配置生效。

/**
 * AnnotationDrivenBeanDefinitionParser的内部类
 * <p>
 * 尝试注册一个InfrastructureAdvisorAutoProxyCreator类型的自动代理创建者
 * 并且配置AOP事务相关的一些基础bean定义,比如事务通知器、事务拦截器、事务属性源
 */
private static class AopAutoProxyConfigurer {
    /**
     * 配置自动代理创建者
     */
    public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {
        /*
         * 如有必要,注册一个InfrastructureAdvisorAutoProxyCreator类型的AutoProxyCreator
         * 并且配置proxy-target-class与expose-proxy属性
         */
        AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);
        //获取事务通知器的banName,默认就是"org.springframework.transaction.config.internalTransactionAdvisor"
        String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;
        /*
         * 如果目前不包含该名称的bean,那么将会注册一个BeanFactoryTransactionAttributeSourceAdvisor类型的注解专用事务通知器
         * 并且配置TransactionInterceptor事务拦截器以及AnnotationTransactionAttributeSource注解事务属性源的bean定义
         *
         * 这里能够看出,即使可能存在多个<tx:annotation-driven/>标签,仍然只会有一个标签的配置生效
         */
        if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {
            Object eleSource = parserContext.extractSource(element);

            // 创建一个bean定义,class为"org.springframework.transaction.annotation.AnnotationTransactionAttributeSource"
            //就是一个适用于注解的事务属性源
            RootBeanDefinition sourceDef = new RootBeanDefinition(
                    "org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");
            sourceDef.setSource(eleSource);
            sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
            //注册事物属性源到容器中并且返回beanName
            String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);

            //创建TransactionInterceptor事务拦截器的bean定义
            RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);
            interceptorDef.setSource(eleSource);
            interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
            /*
             * 注册事务管理器到事务拦截器中
             * 实际上就是设置TransactionInterceptor的transactionManagerBeanName属性指向一个事务管理器的bean
             */
            registerTransactionManager(element, interceptorDef);
            interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
            //注册拦截器到容器中并且返回beanName
            String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);

            // Create the TransactionAttributeSourceAdvisor definition.
            /*
             * 创建一个TransactionAttributeSourceAdvisor的bean定义
             * 实际类型为BeanFactoryTransactionAttributeSourceAdvisor,就是一个事务通知器
             */
            RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);
            advisorDef.setSource(eleSource);
            advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
            //设置transactionAttributeSource属性,就是AnnotationTransactionAttributeSource事务属性源
            advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
            //设置adviceBeanName属性,就是TransactionInterceptor事务拦截器
            advisorDef.getPropertyValues().add("adviceBeanName", interceptorName);
            //设置事务通知器的order属性
            if (element.hasAttribute("order")) {
                advisorDef.getPropertyValues().add("order", element.getAttribute("order"));
            }
            //将当前事务通知器的bean定义注册到容器中,name为"org.springframework.transaction.config.internalTransactionAdvisor"
            parserContext.getRegistry().registerBeanDefinition(txAdvisorBeanName, advisorDef);
            //发布事件
            CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);
            compositeDef.addNestedComponent(new BeanComponentDefinition(sourceDef, sourceName));
            compositeDef.addNestedComponent(new BeanComponentDefinition(interceptorDef, interceptorName));
            compositeDef.addNestedComponent(new BeanComponentDefinition(advisorDef, txAdvisorBeanName));
            parserContext.registerComponent(compositeDef);
        }
    }
}

/**
 1. AnnotationDrivenBeanDefinitionParser的方法
 2. <p>
 3. 注册事务管理器到事务拦截器中
 4.  5. @param element <tx:annotation-driven/>标签元素
 6. @param def     事务拦截器的bean定义
 */
private static void registerTransactionManager(Element element, BeanDefinition def) {
    //通过TxNamespaceHandler.getTransactionManagerName来获取事务管理器的beanName
    //将会解析<tx:annotation-driven/>标签的transaction-manager属性,默认值同样是transactionManager
    def.getPropertyValues().add("transactionManagerBeanName",
            TxNamespaceHandler.getTransactionManagerName(element));
}

1.2.1 registerAutoProxyCreatorIfNecessary注册自动代理创建者

  如有必要,注册一个InfrastructureAdvisorAutoProxyCreator类型的AutoProxyCreator。该方法的源码与我们在此前的Spring AOP源码(1)—<aop:config/>AOP配置标签解析【一万字】的文章中讲过的registerAspectJAutoProxyCreatorIfNecessary方法基本一致。只不过AutoProxyCreator的类型变成了InfrastructureAdvisorAutoProxyCreator。
该方法分为三步,我们在此前已经讲过具体的源码了,在此不再赘述:

  1. 调用AopConfigUtils.registerAutoProxyCreatorIfNecessary,尝试注册一个名为"org.springframework.aop.config.internalAutoProxyCreator",类型为InfrastructureAdvisorAutoProxyCreator的自动代理创建者的bean定义。
  2. 调用useClassProxyingIfNecessary,解析proxy-target-class与expose-proxy属性。
  3. 调用registerComponentIfNecessary注册组件,这里的注册是指存放到外层方法新建的CompositeComponentDefinition对象的内部集合中或者广播事件,而不是注册到注册表中。
/**
 * AopNamespaceUtils的方法
 * <p>
 * 如有必要,注册一个InfrastructureAdvisorAutoProxyCreator类型的AutoProxyCreator
 * <p>
 * 该方法的源码与我们在此前的<aop:config/>标签解析部分讲过的registerAspectJAutoProxyCreatorIfNecessary方法基本一致
 * 只不过AutoProxyCreator的类型变成了InfrastructureAdvisorAutoProxyCreator
 */
public static void registerAutoProxyCreatorIfNecessary(
        ParserContext parserContext, Element sourceElement) {
    /*
     * 1 尝试注册或者升级一个名为"org.springframework.aop.config.internalAutoProxyCreator"
     * 类型为InfrastructureAdvisorAutoProxyCreator的自动代理创建者的bean定义
     */
    BeanDefinition beanDefinition = AopConfigUtils.registerAutoProxyCreatorIfNecessary(
            parserContext.getRegistry(), parserContext.extractSource(sourceElement));
    /*
     * 2 解析proxy-target-class与expose-proxy属性
     * proxy-target-class用于设置代理模式,默认是优先JDK动态代理,其次CGLIB代理,可以指定为CGLIB代理
     * expose-proxy用于暴露代理对象,主要用来解决同一个目标类的方法互相调用时代理不生效的问题
     */
    useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
    /*
     * 3 注册组件,这里的注册是指存放到外层方法新建的CompositeComponentDefinition对象的内部集合中或者广播事件,而不是注册到注册表中
     */
    registerComponentIfNecessary(beanDefinition, parserContext);
}

/**
 1. AopConfigUtils的方法
 2. <p>
 3. 注册/升级自动代理创建者为InfrastructureAdvisorAutoProxyCreator类型
 */
@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(
        BeanDefinitionRegistry registry, @Nullable Object source) {
    /*
     * 注册/升级自动代理创建者为InfrastructureAdvisorAutoProxyCreator类型
     * 这个方法我们在此前的<aop:config/>标签解析部分也讲过了
     */
    return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}

2 小结

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

  1. 尝试向容器注册名为org.springframework.transaction.config.internalTransactionalEventListenerFactory的TransactionalEventListenerFactory类型的事务事件监听器工厂的bean定义,该bean用于解析@TransactionalEventListener注解方法为一个ApplicationListenerMethodTransactionalAdapter监听器。
  2. 还会尝试注册一个名为org.springframework.aop.config.internalAutoProxyCreator的InfrastructureAdvisorAutoProxyCreator类型的自动代理创建者的bean定义,该bean用于创建代理对象。但是该beanName的bean定义在容器中全局只会注册一个,并且有优先级,这一点我们在此前Spring AOP源码(1)—<aop:config/>AOP配置标签解析【一万字】的文章中就讲过了。
  3. 还会尝试配置AOP事务相关的一些基础bean定义,比如配置BeanFactoryTransactionAttributeSourceAdvisor事务通知器、AnnotationTransactionAttributeSource注解事务属性源(专门用于解析事务注解)、TransactionInterceptor事务拦截器等。

  总体来说,源码比较简单!当然前提是在我们理解了Spring AOP的源码之后才能得出这样的结论。

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

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

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

刘Java

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

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

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

打赏作者

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

抵扣说明:

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

余额充值