老王读Spring Transaction从EnableTransactionManagement顺藤摸瓜,研究@Transactional的实现原理

Posted 老王学源码

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了老王读Spring Transaction从EnableTransactionManagement顺藤摸瓜,研究@Transactional的实现原理相关的知识,希望对你有一定的参考价值。

@TOC

前言

Spring 对事务的封装是一个相对独立的功能,通过 spring-tx-5.3.9.jar 来进行支持。
里面的代码量也不大,我们完全可以像翻书的目录一样,浏览一下 spring-tx 的包结构和类,站在一个高的角度来审视一下 Spring 对事务的封装。

版本约定

spring-tx 5.3.9 (通过 SpringBoot 2.5.3 间接引入的依赖)

正文

浏览 spring-tx-5.3.9.jar ,我们大致可以挑出里面几个比较核心的类

org.springframework.transaction.annotation.Transactional  
org.springframework.transaction.annotation.EnableTransactionManagement  
org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration  

org.springframework.transaction.interceptor.TransactionAspectSupport  
org.springframework.transaction.interceptor.TransactionInterceptor    
org.springframework.transaction.interceptor.TransactionAttribute  

org.springframework.transaction.TransactionManager  
org.springframework.transaction.PlatformTransactionManager  
org.springframework.transaction.TransactionDefinition  
org.springframework.transaction.SavepointManager  

通常我们使用 Spring 的事务功能,都需要添加 @EnableTransactionManagement 来开启事务管理功能。
那就从 EnableTransactionManagement 开始看起

EnableTransactionManagement

@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement 

    /**
     * 指定是否创建基于子类(CGLIB)的代理,而不是基于 jdk proxy 的代理。默认值为false。
     * 注意: 它是一个全局设置,设置为 true 将影响所有需要代理的 Spring 托管 bean,而不仅仅是那些标记为 @Transactional 的 bean。
     */
    boolean proxyTargetClass() default false;

    AdviceMode mode() default AdviceMode.PROXY;

    int order() default Ordered.LOWEST_PRECEDENCE;

可以看到,@EnableTransactionManagement 注解会引入 @Import(TransactionManagementConfigurationSelector.class)

public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> 

    @Override
    protected String[] selectImports(AdviceMode adviceMode) 
        switch (adviceMode) 
            case PROXY: // 默认是走这个分支
                return new String[] AutoProxyRegistrar.class.getName(),
                        ProxyTransactionManagementConfiguration.class.getName();
            case ASPECTJ:
                return new String[] determineTransactionAspectClass();
            default:
                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);
    

可以看到,TransactionManagementConfigurationSelector 会引入一个配置类: ProxyTransactionManagementConfiguration
ProxyTransactionManagementConfiguration 是 Spring 事务配置的核心类

ProxyTransactionManagementConfiguration——Spring 事务配置的核心类

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

    // 事务 Advisor,实现 Spring 切面事务的核心
    @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
            TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) 

        BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
        advisor.setTransactionAttributeSource(transactionAttributeSource);
        advisor.setAdvice(transactionInterceptor);
        if (this.enableTx != null) 
            advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
        
        return advisor;
    

    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public TransactionAttributeSource transactionAttributeSource() 
        return new AnnotationTransactionAttributeSource();
    

    // 事务拦截器
    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) 
        TransactionInterceptor interceptor = new TransactionInterceptor();
        interceptor.setTransactionAttributeSource(transactionAttributeSource);
        if (this.txManager != null) 
            interceptor.setTransactionManager(this.txManager);
        
        return interceptor;
    

可以看到,这里面配置了一个 Advisor(Spring AOP 中的概念)——BeanFactoryTransactionAttributeSourceAdvisor

BeanFactoryTransactionAttributeSourceAdvisor 中设置的 Pointcut 和 Advice 分别是:

  • Pointcut: TransactionAttributeSourcePointcut
  • Advice: TransactionInterceptor

找到了 Pointcut,也就知道了它是怎么匹配 joinpoint 的。
找到了 Advice,也就知道了它在 joinpoint 上执行的 AOP 拦截逻辑是什么。(即: @Transactional 的实现逻辑)

TransactionInterceptor

事务拦截器,是实现 Spring 事务拦截的核心类。

public Object invoke(MethodInvocation invocation) throws Throwable 
    // Work out the target class: may be @code null.
    // The TransactionAttributeSource should be passed the target class
    // as well as the method, which may be from an interface.
    Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);

    // Adapt to TransactionAspectSupports invokeWithinTransaction...
    return invokeWithinTransaction(invocation.getMethod(), targetClass, new CoroutinesInvocationCallback() 
        @Override
        @Nullable
        public Object proceedWithInvocation() throws Throwable 
            return invocation.proceed();
        
        @Override
        public Object getTarget() 
            return invocation.getThis();
        
        @Override
        public Object[] getArguments() 
            return invocation.getArguments();
        
    );

从源码中可以看到,业务方法的执行被封装在 MethodInvocation 中,事务的处理是放在 TransactionAspectSupport#invokeWithinTransaction() 方法中实现的。

TransactionAttributeSource

用于获取事务元数据信息的接口。事务的元数据信息就包括: 使用的事务管理器、事务隔离级别、事务传播特性、事务超时时间、针对哪些异常进行回滚等

TransactionAttributeSource 获取到的事务元数据信息主要是提供给 TransactionInterceptor 来使用的。
TransactionAttributeSource 有多种实现,其中最常用的是 AnnotationTransactionAttributeSource,它主要用来处理注解类的事务元数据,即: @Transactional

小结

Spring 对事务的封装是一个相对独立的功能,通过 spring-tx-5.3.9.jar 来进行支持。
Spring 注解事务是通过 AOP 来实现的。具体的实现是放在 TransactionInterceptor 这个 Advice 类中。

事务注解中的事务元数据信息的解析是通过 AnnotationTransactionAttributeSource 来处理的。



如果本文对你有所帮助,欢迎点赞收藏
有关 Spring 源码方面的问题欢迎留言一起交流...

公众号后台回复:下载IoC 或者 下载AOP 可以免费下载源码测试工程…

阅读更多文章,请关注公众号: 老王学源码

以上是关于老王读Spring Transaction从EnableTransactionManagement顺藤摸瓜,研究@Transactional的实现原理的主要内容,如果未能解决你的问题,请参考以下文章

老王读Spring Transaction-4Spring事务管理的核心原理——PlatformTransactionManager&TransactionStatus

老王读Spring Transaction-6spring-tx与DataSource连接池整合的原理

老王读Spring IoC-5Spring IoC 小结——控制反转依赖注入

老王读Spring IoC-3Spring bean 的创建过程

老王读Spring IoC-2Spring IoC之BeanDefinition扫描注册的原理

#yyds干货盘点# 老王读Spring AOP-4Spring AOP 与Spring IoC 结合的过程 && ProxyFactory 解析