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

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 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属性中。

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



目录
相关文章
|
2月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
86 2
|
9天前
|
设计模式 XML Java
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
本文详细介绍了Spring框架的核心功能,并通过手写自定义Spring框架的方式,深入理解了Spring的IOC(控制反转)和DI(依赖注入)功能,并且学会实际运用设计模式到真实开发中。
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
|
2月前
|
XML Java 数据库连接
Spring高手之路25——深入解析事务管理的切面本质
本篇文章将带你深入解析Spring事务管理的切面本质,通过AOP手动实现 @Transactional 基本功能,并探讨PlatformTransactionManager的设计和事务拦截器TransactionInterceptor的工作原理,结合时序图详细展示事务管理流程,最后引导分析 @Transactional 的代理机制源码,帮助你全面掌握Spring事务管理。
38 2
Spring高手之路25——深入解析事务管理的切面本质
|
1月前
|
Android开发 开发者 Python
通过标签清理微信好友:Python自动化脚本解析
微信已成为日常生活中的重要社交工具,但随着使用时间增长,好友列表可能变得臃肿。本文介绍了一个基于 Python 的自动化脚本,利用 `uiautomator2` 库,通过模拟用户操作实现根据标签批量清理微信好友的功能。脚本包括环境准备、类定义、方法实现等部分,详细解析了如何通过标签筛选并删除好友,适合需要批量管理微信好友的用户。
51 7
|
29天前
|
存储 缓存 Java
Spring面试必问:手写Spring IoC 循环依赖底层源码剖析
在Spring框架中,IoC(Inversion of Control,控制反转)是一个核心概念,它允许容器管理对象的生命周期和依赖关系。然而,在实际应用中,我们可能会遇到对象间的循环依赖问题。本文将深入探讨Spring如何解决IoC中的循环依赖问题,并通过手写源码的方式,让你对其底层原理有一个全新的认识。
51 2
|
2月前
|
Java 开发者 Spring
深入解析:Spring AOP的底层实现机制
在现代软件开发中,Spring框架的AOP(面向切面编程)功能因其能够有效分离横切关注点(如日志记录、事务管理等)而备受青睐。本文将深入探讨Spring AOP的底层原理,揭示其如何通过动态代理技术实现方法的增强。
75 8
|
2月前
|
前端开发 Java 开发者
Spring MVC中的请求映射:@RequestMapping注解深度解析
在Spring MVC框架中,`@RequestMapping`注解是实现请求映射的关键,它将HTTP请求映射到相应的处理器方法上。本文将深入探讨`@RequestMapping`注解的工作原理、使用方法以及最佳实践,为开发者提供一份详尽的技术干货。
135 2
|
2月前
|
前端开发 Java Spring
探索Spring MVC:@Controller注解的全面解析
在Spring MVC框架中,`@Controller`注解是构建Web应用程序的基石之一。它不仅简化了控制器的定义,还提供了一种优雅的方式来处理HTTP请求。本文将全面解析`@Controller`注解,包括其定义、用法、以及在Spring MVC中的作用。
57 2
|
2月前
|
前端开发 Java Maven
深入解析:如何用 Spring Boot 实现分页和排序
深入解析:如何用 Spring Boot 实现分页和排序
59 2
|
2月前
|
Java 开发者 Spring
Spring AOP深度解析:探秘动态代理与增强逻辑
Spring框架中的AOP(Aspect-Oriented Programming,面向切面编程)功能为开发者提供了一种强大的工具,用以将横切关注点(如日志、事务管理等)与业务逻辑分离。本文将深入探讨Spring AOP的底层原理,包括动态代理机制和增强逻辑的实现。
48 4

推荐镜像

更多