Spring源码剖析之Transactional事务

简介: 我们知道使用@Transactional,要满足以下条件1、配置数据源 DataSource2、配置事务管理器 PlatformTransactionManager3、配置类上标识 @EnableTransactionManagement

准备

我们知道使用@Transactional,要满足以下条件

1、配置数据源 DataSource
2、配置事务管理器 PlatformTransactionManager
3、配置类上标识 @EnableTransactionManagement

@Configuration
@PropertySource(value = {"classpath:jdbc.properties"},encoding = "UTF-8")
public class TransactionalConfig {

    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;
    @Value("${jdbc.driver}")
    private String driver;

    /**
     * 配置数据源
     * @return
     */
    @Bean
    public DataSource dataSource(){
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setUrl(url);
        druidDataSource.setUsername(username);
        druidDataSource.setPassword(password);
        druidDataSource.setDriverClassName(driver);
        return druidDataSource;
    }

    /**
     * 配置事务管理器
     * @param dataSource
     * @return
     */
    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource){
        DataSourceTransactionManager manager = new DataSourceTransactionManager();
        manager.setDataSource(dataSource);
        return manager;
    }


    /**
     * 配置jdbcTemplate
     * @param dataSource
     * @return
     */
    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource){
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        jdbcTemplate.setDataSource(dataSource);
        return jdbcTemplate;
    }

}
/**
 * 核心配置类
 */
@Configuration
@ComponentScan({"com.xiaoxu"})
@EnableAspectJAutoProxy(exposeProxy = true)   // 开启Spring对注解AOP的支持
@EnableTransactionManagement  // 开启Spring对注解事务支持
public class ApplicationContextConfiguration {

}

@Transactional剖析

1、 配置类上的注解@EnableTransactionManagement ,通过@Import 引入TransactionManagementConfigurationSelector 向容器中导入组件,一个是AutoProxyRegistrar和 ProxyTransactionManagementConfiguration

在这里插入图片描述

2、AutoProxyRegistrar 本质上是ImportBeanDefinitonRegistar,BeanDefinitionRegistar的主要作用在于加载默认定义的BeanDefintion。

他的调用时机是 容器refresh中的 invokeBeanFactoryPostProcessor中执行,这个方法主要是通过ConfigurationClassPostProcessor 处理核心配置类,解析配置类上的注解,例如@ComponentScan,@Import实现组件扫描并注册到IOC容器中。

在解析@Import完后找到了AutoProxyRegistrar,实例化 AutoProxyRegistrar(注意:并非所有组件都会放入一级缓存,只有需要才放入),调用 registerBeanDefinitions,向容器中注入一个组件AspectJAutoProxyCreator,该组件主要实现对对象进行代理

在这里插入图片描述

如果有必要注册AutoProxyCreator
在这里插入图片描述

注册AspectjAutoProxyCreator,该组件主要实现对对象进行代理
在这里插入图片描述

而且 这个组件不就是 @EnbaleAspectJAutoProxy注解,向容器中注册的组件嘛。

也就是说,AutoProxyRegister和AspectJAutoProxyRegistrar 本质一样,都是向容器中注入组件AspectjAutoProxyCreator,实现对目标对象生成代理

在这里插入图片描述
在这里插入图片描述

3、ProxyTransactionManagementConfiguration 事务管理配置类

ProxyTransactionManagementConfiguration是一个配置类,注入了三个组件

1、transactionAdvisor 事务增强器,其中注入了事务属性解析器和事务拦截器
2、transactionAttributeSource事务属性解析器
3、transactionInterceptor 事务拦截器

@Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {

    @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    // 注入事务增强器
    public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
        // 事务增强器
        BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
        // 向事务增强中注入属性解析器TransactionAttributeSource
        advisor.setTransactionAttributeSource(transactionAttributeSource());
        // 向事务增强器中设置事务拦截器TransactionInterceptor
        advisor.setAdvice(transactionInterceptor());
        if (this.enableTx != null) {
            advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
        }
        return advisor;
    }

    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    // 注入事务属性解析器transactionAttributeSource
    public TransactionAttributeSource transactionAttributeSource() {
        return new AnnotationTransactionAttributeSource();
    }

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

}

4、transactionAttributeSource 事务属性解析器,实现对@Transactional的解析

创建事务属性解析器

在这里插入图片描述

决定事务属性解析器,来解析@Transactional

在这里插入图片描述

通过指定的事务解析器,解析事务注解

在这里插入图片描述

5、TransactionInterceptor 事务拦截器,实现对@Transactional事务方法拦截调用,如果需要调用,则调用,不需要则调用,如果没有事务,那么创建事务,并且从数据库连接池中获取连接,通过ThreadLocal放入当前线程中,并设置AutoCommit为false,然后执行目标方法,如果出现异常,进行回滚,最后提交事务

在这里插入图片描述

@Nullable
    protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
            final InvocationCallback invocation) throws Throwable {

        
        // 获取事务属性解析器
        TransactionAttributeSource tas = getTransactionAttributeSource();
        final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
        // 获取事务管理器
        final PlatformTransactionManager tm = determineTransactionManager(txAttr);
        final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);

        if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
            // 如果没有事务就创建事务,创建的事务,会从数据库连接池中获取连接,通过ThreadLoacl放入当前线程中,并设置connect.setAutoCommit= false
            TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
            Object retVal = null;
            try {
                // 调用目标方法
                retVal = invocation.proceedWithInvocation();
            }
            catch (Throwable ex) {
                // 如果目标方法抛异常,那么进行回滚
                completeTransactionAfterThrowing(txInfo, ex);
                throw ex;
            }
            finally {
                cleanupTransactionInfo(txInfo);
            }
            // 如果目标方法正常运行,提交事务
            commitTransactionAfterReturning(txInfo);
            return retVal;
        }
    }

总结

1、容器refresh时,调用invokeBeanFactoryPostProcessor,创建并调用ConfigurationClassPostProcessor解析核心配置类

2、通过解析核心配置类上的@EnableTransactionManagement,调用importSelect实例类中方法,将容器中注入两个重要组件 AutoProxyRegister (自动代理注册器) 和 TransactionManagementConfiguration 事务配置类

3、AutoProxyRegsiter 向容器中注入 ApsectjAutoProxyCreator ,切面自动代理创建器实现 对目标类代理
TransactionManagementConfiguration 事务管理配置类,向容器中注入三个组件

  • 事务属性解析器 TransactionAttributeSource,实现对@Transactional 注解解析
  • 事务拦截器 TransactionInterceptor 实现事务方法拦截
  • 事务增强器,分别注入了属性解析器和拦截器

4、实例化所有BeanPostProcessor包括(AspectAutoProxyCreator)

5、对BeanDefinitionMap中剩余的所有单例Bean,进行实例化 --》 属性赋值,依赖注入 --》 XXXAware --》BeanPostProcessor before --》 bean init
--》AspectAutoProxyCreator 中对需要代理的Bean 进行代理(通过获取当前Bean的所匹配的拦截器/advisor来判断是否需要代理)

6、创建完代理对象后,将原对象,增强方法/拦截器 设置到代理对象中,将代理对象放入一级缓存

7、代理对象调用目标方法,实际上走到了对应的拦截器,拦截器判断当前方法是否是@Transactional的方法,如果是,那么创建事务,从数据库连接池中获取连接,通过ThreadLocal将conn设置到当前线程中,开启事务,设置autoCommit为false

8、调用目标方法,目标方法执行过程中,获取的connetion,也是从当前线程中获取的

9、遇见异常进行回滚

10、事务提交

相关文章
|
2月前
|
SQL Java 关系型数据库
Spring事务传播机制:7种姿势教你玩转"事务接力赛"
事务传播机制是Spring框架中用于管理事务行为的重要概念,它决定了在方法调用时事务如何传递与执行。通过7种传播行为,开发者可以灵活控制事务边界,适应不同业务场景。例如:REQUIRED默认加入或新建事务,REQUIRES_NEW独立开启新事务,NESTED支持嵌套回滚等。合理使用传播机制不仅能保障数据一致性,还能提升系统性能与健壮性。掌握这“七种人格”,才能在复杂业务中游刃有余。
|
3月前
|
Java 关系型数据库 数据库
深度剖析【Spring】事务:万字详解,彻底掌握传播机制与事务原理
在Java开发中,Spring框架通过事务管理机制,帮我们轻松实现了这种“承诺”。它不仅封装了底层复杂的事务控制逻辑(比如手动开启、提交、回滚事务),还提供了灵活的配置方式,让开发者能专注于业务逻辑,而不用纠结于事务细节。
|
8月前
|
Java 关系型数据库 数据库
微服务——SpringBoot使用归纳——Spring Boot事务配置管理——常见问题总结
本文总结了Spring Boot中使用事务的常见问题,虽然通过`@Transactional`注解可以轻松实现事务管理,但在实际项目中仍有许多潜在坑点。文章详细分析了三个典型问题:1) 异常未被捕获导致事务未回滚,需明确指定`rollbackFor`属性;2) 异常被try-catch“吃掉”,应避免在事务方法中直接处理异常;3) 事务范围与锁范围不一致引发并发问题,建议调整锁策略以覆盖事务范围。这些问题看似简单,但一旦发生,排查难度较大,因此开发时需格外留意。最后,文章提供了课程源代码下载地址,供读者实践参考。
209 0
|
3月前
|
设计模式 Java 开发者
如何快速上手【Spring AOP】?从动态代理到源码剖析(下篇)
Spring AOP的实现本质上依赖于代理模式这一经典设计模式。代理模式通过引入代理对象作为目标对象的中间层,实现了对目标对象访问的控制与增强,其核心价值在于解耦核心业务逻辑与横切关注点。在框架设计中,这种模式广泛用于实现功能扩展(如远程调用、延迟加载)、行为拦截(如权限校验、异常处理)等场景,为系统提供了更高的灵活性和可维护性。
|
7月前
|
前端开发 Java 物联网
智慧班牌源码,采用Java + Spring Boot后端框架,搭配Vue2前端技术,支持SaaS云部署
智慧班牌系统是一款基于信息化与物联网技术的校园管理工具,集成电子屏显示、人脸识别及数据交互功能,实现班级信息展示、智能考勤与家校互通。系统采用Java + Spring Boot后端框架,搭配Vue2前端技术,支持SaaS云部署与私有化定制。核心功能涵盖信息发布、考勤管理、教务处理及数据分析,助力校园文化建设与教学优化。其综合性和可扩展性有效打破数据孤岛,提升交互体验并降低管理成本,适用于日常教学、考试管理和应急场景,为智慧校园建设提供全面解决方案。
487 70
|
6月前
|
人工智能 Java 数据库连接
Spring事务失效场景
本文深入探讨了Spring框架中事务管理可能失效的几种常见场景及解决方案,包括事务方法访问级别不当、方法内部自调用、错误的异常处理、事务管理器或数据源配置错误、数据库不支持事务以及不合理的事务传播行为或隔离级别。通过合理配置和正确使用`@Transactional`注解,开发者可以有效避免这些问题,确保应用的数据一致性和完整性。
357 10
|
5月前
|
Java 关系型数据库 MySQL
【Spring】【事务】初学者直呼学会了的Spring事务入门
本文深入解析了Spring事务的核心概念与使用方法。Spring事务是一种数据库事务管理机制,通过确保操作的原子性、一致性、隔离性和持久性(ACID),维护数据完整性。文章详细讲解了声明式事务(@Transactional注解)和编程式事务(TransactionTemplate、PlatformTransactionManager)的区别与用法,并探讨了事务传播行为(如REQUIRED、REQUIRES_NEW等)及隔离级别(如READ_COMMITTED、REPEATABLE_READ)。
452 1
|
Java 数据库连接 应用服务中间件
Spring源码剖析8:Spring事务概述
原文出处: 张开涛 9.1  数据库事务概述 事务首先是一系列操作组成的工作单元,该工作单元内的操作是不可分割的,即要么所有操作都做,要么所有操作都不做,这就是事务。
|
4月前
|
Java Spring 容器
SpringBoot自动配置的原理是什么?
Spring Boot自动配置核心在于@EnableAutoConfiguration注解,它通过@Import导入配置选择器,加载META-INF/spring.factories中定义的自动配置类。这些类根据@Conditional系列注解判断是否生效。但Spring Boot 3.0后已弃用spring.factories,改用新格式的.imports文件进行配置。
884 0

热门文章

最新文章