Spring5源码(41)-tx:annotation-driven 标签解析过程

简介: Spring5源码(41)-tx:annotation-driven 标签解析过程


上一节演示了基于tx标签和基于@Transactional注解的声明式事物的使用过程,本节分析一下基于@Transactional注解的声明式事物的实现过程。

1.快速定位Spring自定义标签解析入口

在上节的配置文件中,通过<tx:annotation-driven transaction-manager="transactionManager"/>开启了注解事物,以此为入口,开始今天的分析。

tx是Spring的自定义标签,在32--aspectj-autoproxy解析及Spring解析自定义标签一节中已经分析过自定义标签的解析过程,Spring通过继承NamespaceHandler自定义命名空间的解析,以此推论,tx标签必然也有自己的命名空间解析器,通过全局搜索,可以找到TxNamespaceHandler类下包含了annotation-driven。通过该方法如果大家再遇到Spring的自定义标签,可通过此方式为入口,快速找到分析入口所在。

2.
解析过程

按照我们之前章节的分析,注册了BeanDefinitionParser之后紧接着就要调用其parse方法对xml标签进行解析。(不清楚该过程的可以参考:32--aspectj-autoproxy解析及Spring解析自定义标签中的分析)。

public class TxNamespaceHandler extends NamespaceHandlerSupport {
    static final String TRANSACTION_MANAGER_ATTRIBUTE = "transaction-manager";
    static final String DEFAULT_TRANSACTION_MANAGER_BEAN_NAME = "transactionManager";
    static String getTransactionManagerName(Element element) {
        return (element.hasAttribute(TRANSACTION_MANAGER_ATTRIBUTE) ?
                element.getAttribute(TRANSACTION_MANAGER_ATTRIBUTE) : DEFAULT_TRANSACTION_MANAGER_BEAN_NAME);
    }
    @Override
    public void init() {
        registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());
        // 注册AnnotationDrivenBeanDefinitionParser
        registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
        registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());
    }
}

在TxNamespaceHandler中完成了对AnnotationDrivenBeanDefinitionParser的注册,接下来就要调用其parse方法。

@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
    // 1、注册TransactionalEventListenerFactory
    registerTransactionalEventListenerFactory(parserContext);
    // 2、解析标签的mode属性
    String mode = element.getAttribute("mode");
    if ("aspectj".equals(mode)) {
        // mode="aspectj"
        // aspectj模式
        registerTransactionAspect(element, parserContext);
        if (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader())) {
            registerJtaTransactionAspect(element, parserContext);
        }
    }
    else {
        // mode="proxy"
        // proxy模式
        AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);
    }
    return null;
}

在parse方法里,首先注册了TransactionalEventListenerFactory,然后解析<tx:annotation-driven/>的mode属性,这里我们主要分析proxy模式。

/**
 * 在代理模式下引入AOP框架依赖关系的内部类。
 * Inner class to just introduce an AOP framework dependency when actually in proxy mode.
 */
private static class AopAutoProxyConfigurer {
    public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {
        // 1、注册InfrastructureAdvisorAutoProxyCreator  Infrastructure-->基础设施
        // 注意:区分@AspectJ:@AspectJ注册的是AnnotationAwareAspectJAutoProxyCreator
        AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);
        // TRANSACTION_ADVISOR_BEAN_NAME-->org.springframework.transaction.config.internalTransactionAdvisor
        String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;
        if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {
            Object eleSource = parserContext.extractSource(element);
            // Create the TransactionAttributeSource definition.
            // 2、创建AnnotationTransactionAttributeSource的BeanDefinition
            RootBeanDefinition sourceDef = new RootBeanDefinition(
                    "org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");
            sourceDef.setSource(eleSource);
            // 设置Role属性,ROLE_INFRASTRUCTURE表示Spring的内部bean
            sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
            // 生成bean名称
            String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);
            // Create the TransactionInterceptor definition.
            // 3、创建TransactionInterceptor的BeanDefinition
            RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);
            interceptorDef.setSource(eleSource);
            // 设置Role属性,ROLE_INFRASTRUCTURE表示Spring的内部bean
            interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
            // 注册事物管理器
            registerTransactionManager(element, interceptorDef);
            // 将AnnotationTransactionAttributeSource注入到TransactionInterceptor的transactionAttributeSource属性中
            interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
            // 生成bean名称
            String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);
            // Create the TransactionAttributeSourceAdvisor definition.
            // 4、创建BeanFactoryTransactionAttributeSourceAdvisor的BeanDefinition
            RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);
            advisorDef.setSource(eleSource);
            // 设置Role属性,ROLE_INFRASTRUCTURE表示Spring的内部bean
            advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
            // 将上一步创建的AnnotationTransactionAttributeSource注入到
            // BeanFactoryTransactionAttributeSourceAdvisor的transactionAttributeSource属性中
            advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
            // 将上一步创建的TransactionInterceptor注入到
            // BeanFactoryTransactionAttributeSourceAdvisor的adviceBeanName属性中
            advisorDef.getPropertyValues().add("adviceBeanName", interceptorName);
            // 解析<tx:annotation-driven>的order属性标签
            if (element.hasAttribute("order")) {
                advisorDef.getPropertyValues().add("order", element.getAttribute("order"));
            }
            // 将TransactionAttributeSourceAdvisor以txAdvisorBeanName为名称注册到IOC容器中
            parserContext.getRegistry().registerBeanDefinition(txAdvisorBeanName, advisorDef);
            /**
             * 通过上面的操作:
             * 1、创建AnnotationTransactionAttributeSource的BeanDefinition
             * 2、创建TransactionInterceptor的BeanDefinition
             * 3、创建TransactionAttributeSourceAdvisor的BeanDefinition,
             *    并将第一步,第二步创建的BeanDefinition注入到transactionAttributeSource和adviceBeanName中
             *
             *    BeanFactoryTransactionAttributeSourceAdvisor-->TransactionInterceptor
             *    BeanFactoryTransactionAttributeSourceAdvisor-->AnnotationTransactionAttributeSource
             */
            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);
        }
    }
}

上面的这段代码,看起来枯燥无比,但这段代是Spring声明式事物的核心所在,下面对其中的细节逐一分析。

2.1注册InfrastructureAdvisorAutoProxyCreator

在之前的章节分析SpringAOP时,曾经注册了AnnotationAwareAspectJAutoProxyCreator,该类的作用是为目标对象自动创建代理,该类间接实现了BeanPostProcessor接口,所以会在bean的实例化前后调用postProcessBeforeInstantiation和postProcessAfterInitialization方法,这些在之前的章节中已经反复讲解过。

那么InfrastructureAdvisorAutoProxyCreator类是否有同样的作用呢?来查看一下其类继承关系不难发现其也间接实现了BeanPostProcessor接口,那么只要找到该类或者其父类中的postProcessBeforeInstantiation方法和postProcessAfterInitialization方法,就不难分析出其作用。这了也是一点点源码分析的小技巧,关于此类的作用,我们留在后面分析,接下来继续看configureAutoProxyCreator方法。


在这里插入图片描述

2.2 创建AnnotationTransactionAttributeSource的BeanDefinition

该过程比较简单,但是要分析一下AnnotationTransactionAttributeSource的作用。打开该类的代码,看起来毫无头绪,这时候不妨查看一下其类继承关系,或许就有新的发现,这也是阅读源码的小技巧。

在这里插入图片描述


可以看到该类实现了TransactionAttributeSource接口,该接口只提供了一个获取TransactionAttribute的方法TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass);。TransactionAttribute实现了TransactionDefinition接口,该接口提供了Spring事物的传播特性以及事物隔离级别等定义。

综合上述分析,大致可以了解到AnnotationTransactionAttributeSource已经可以获取到事物属性,再通过该类是Annotation开头,也可以再次猜测该类是获取类、接口、方法上的事物注解属性。当然这里只是猜测,到底是不是呢?我们留在后面分析。

2.3 创建TransactionInterceptor的BeanDefinition

TransactionInterceptor是Spring声明式事物管理器的基础,查看其类图结构,TransactionInterceptor继承了TransactionAspectSupport并实现了MethodInterceptor接口。TransactionAspectSupport提供了对事物支持的能力,而MethodInterceptor我们之前已经介绍过,可以用来实现环绕增强。从此我们大致可以推断出,Spring的事物管理是基于环绕增强的。该类的具体方法以及调用过程留在后面分析。


在这里插入图片描述

2.4 创建TransactionAttributeSourceAdvisor的BeanDefinition并注册bean

上面已经创建了事物属性定义、事物增强定义、那么接下来就应该创建切面了。


在这里插入图片描述

从类图上看到BeanFactoryTransactionAttributeSourceAdvisor是PointcutAdvisor类型的切面,创建了该bean的定义之后,又将上面创建的AnnotationTransactionAttributeSource注入到transactionAttributeSource属性中;将TransactionInterceptor注入到adviceBeanName属性中。

当然分析到这里的时候,大家有可能会非常迷茫,不过没关系,我们在后面的章节会详细分析。



目录
相关文章
|
3天前
|
canal 缓存 关系型数据库
Spring Boot整合canal实现数据一致性解决方案解析-部署+实战
Spring Boot整合canal实现数据一致性解决方案解析-部署+实战
|
3天前
|
XML 人工智能 Java
Spring Bean名称生成规则(含源码解析、自定义Spring Bean名称方式)
Spring Bean名称生成规则(含源码解析、自定义Spring Bean名称方式)
|
10天前
|
Java 关系型数据库 MySQL
一套java+ spring boot与vue+ mysql技术开发的UWB高精度工厂人员定位全套系统源码有应用案例
UWB (ULTRA WIDE BAND, UWB) 技术是一种无线载波通讯技术,它不采用正弦载波,而是利用纳秒级的非正弦波窄脉冲传输数据,因此其所占的频谱范围很宽。一套UWB精确定位系统,最高定位精度可达10cm,具有高精度,高动态,高容量,低功耗的应用。
一套java+ spring boot与vue+ mysql技术开发的UWB高精度工厂人员定位全套系统源码有应用案例
|
11天前
yolo-world 源码解析(六)(2)
yolo-world 源码解析(六)
22 0
|
11天前
yolo-world 源码解析(六)(1)
yolo-world 源码解析(六)
16 0
|
11天前
yolo-world 源码解析(五)(4)
yolo-world 源码解析(五)
22 0
|
11天前
yolo-world 源码解析(五)(1)
yolo-world 源码解析(五)
33 0
|
30天前
|
Java 应用服务中间件 Maven
SpringBoot 项目瘦身指南
SpringBoot 项目瘦身指南
44 0
|
2月前
|
缓存 Java Maven
Spring Boot自动配置原理
Spring Boot自动配置原理
48 0
|
1月前
|
缓存 安全 Java
Spring Boot 面试题及答案整理,最新面试题
Spring Boot 面试题及答案整理,最新面试题
113 0

推荐镜像

更多