Spring事务学习笔记(一)

1. 事务

指访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。 事务由事务开始(begin transaction)和事务结束(end transaction)之间执行的全体操作组成。

特性:

  • 原子性(atomicity):一个事务是一个不可分割的工作单位,事务中包括的操作要么都做,要么都不做。
  • 一致性(consistency):事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
  • 隔离性(isolation):一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
  • 持久性(durability):或永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。

2.Spring编程式事务

2.1 概念

即通过编码方式实现事务,即类似于JDBC编程实现事务管理。管理使用TransactionTemplate(Spring推荐)或者直接使用底层的PlatformTransactionManager。

2.2 重要接口
  • TransactionDefinition:定义了Spring兼容的事务属性(比如事务隔离级别、事务传播、事务超时、是否只读状态)。
  • TransactionStatus:代表了事务的具体运行状态(获取事务运行状态的信息,也可以通过该接口间接回滚事务等操作)。
  • PlatformTransactionManager:事务管理器接口(定义了一组行为,具体实现交由不同的持久化框架来完成—类比JDBC)

3. Spring声明式事务

3.1 概念

本质是AOP思想的实现,即对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。

3.2 实现方式
  • @Transactional注解实现
  • xml配置
3.3 @Transactional注解属性配置
  • readOnly:设置当前事务是否为只读事务,设置为true表示只读,false则表示可读写,默认值为false。
@Transactional(readOnly=true)
  • rollbackFor: 设置需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,则进行事务回滚。
指定单一异常类:@Transactional(rollbackFor=RuntimeException.class)
指定多个异常类:@Transactional(rollbackFor={RuntimeException.class, Exception.class})
  • rollbackForClassName:该属性用于设置需要进行回滚的异常类名称数组,当方法中抛出指定异常名称数组中的异常时,则进行事务回滚。
指定单一异常类名称:@Transactional(rollbackForClassName="RuntimeException")
指定多个异常类名称:@Transactional(rollbackForClassName={"RuntimeException","Exception"})
  • noRollbackFor: 设置不需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,不进行事务回滚。
指定单一异常类:@Transactional(noRollbackFor=RuntimeException.class)
指定多个异常类:@Transactional(noRollbackFor={RuntimeException.class, Exception.class})
  • noRollbackForClassName: 设置不需要进行回滚的异常类名称数组,当方法中抛出指定异常名称数组中的异常时,不进行事务回滚。
指定单一异常类名称:@Transactional(noRollbackForClassName="RuntimeException")
指定多个异常类名称:@Transactional(noRollbackForClassName={"RuntimeException","Exception"})
  • propagation:设置事务的传播行为。
@Transactional(propagation=Propagation.NOT_SUPPORTED)
  • isolation:设置底层数据库的事务隔离级别,事务隔离级别用于处理多事务并发的情况,通常使用数据库的默认隔离级别即可,基本不需要进行设置。
  • timeout:设置事务的超时秒数,默认值为 -1 表示永不超时
3.4 @Transactional注意事项
  1. @Transactional 只能被应用到public方法上, 对于其它非public的方法,如果标记了@Transactional不会报错,但方法没有事务功能。

4. Spring 事务传播行为

Spring 事务传播行为:用来解决业务层之间调用的事务的关系。

类型外部不存在事务外部存在事务范例
REQUIRED(默认)开启新的事务融合到外部事务中@Transactional(propagation = Propagation.REQUIRED)适用增删改查
SUPPORTS不开启新的事务融合到外部事务中@Transactional(propagation = Propagation.SUPPORTS)适用查询
REQUIRES_NEW开启新的事务不用外部事务,创建新的事务@Transactional(propagation = Propagation.REQUIRES_NEW)适用内部事务和外部事务不存在业务关联情况,如日志
NOT_SUPPORTED不开启新的事务不用外部事务@Transactional(propagation = Propagation.NOT_SUPPORTED) 不常用
NEVER开启新的事务抛出异常@Transactional(propagation = Propagation.NEVER )不常用
MANDATORY抛出异常融合到外部事务中@Transactional(propagation = Propagation.MANDATORY)不常用
NESTED开启新的事务融合到外部事务中,SavePoint机制,外层影响内层, 内层不会影响外层@Transactional(propagation = Propagation.NESTED)不常用

5. @Transactional原理大致解析

基于注解的声明式事务,必不可少的一步是在容器配置类上加@EnableTransactionManagement注解。

5.1 源码解析

@EnableTransactionManagement源码:

在这里插入图片描述
TransactionManagementConfigurationSelector类源码:

  • AutoProxyRegistrar:相当于一个自定义组件注册器,在容器中注册了一个后置处理器。
  • ProxyTransactionManagementConfiguration:是一个容器配置类,在其中注册了事务增强器。

在这里插入图片描述
registerAutoProxyCreatorIfNecessary方法:

最终在容器中注册了一个InfrastructureAdvisorAutoProxyCreator类
在这里插入图片描述
InfrastructureAdvisorAutoProxyCreator类:

这个类实现了SmartInstantiationAwareBeanPostProcessor,即这是一个后置处理器。所以,声明式事务是springAOP思想的一种应用在这里插入图片描述

ProxyTransactionManagementConfiguration类源码:

这个类注册了一个组件transactionAdvisor(事务增强器),然后又在这个事务增强器中又注入了两个属性:

  • transactionAttributeSource:属性解析器
  • transactionInterceptor:事务拦截器

在这里插入图片描述
属性解析器AnnotationTransactionAttributeSource类:

方法中主要添加了多种注解解析器(TransactionAnnotationParser),例如spring的、jta的、ejb的。下面只看spring的注解解析器源码。
在这里插入图片描述

spring的注解解析器SpringTransactionAnnotationParser类:

方法主要用来解析@Transactional注解的属性
在这里插入图片描述

事务拦截器TransactionInterceptor类:

最终返回:

 return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);

在这里插入图片描述

invokeWithinTransaction方法:

@Nullable
    protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass, TransactionAspectSupport.InvocationCallback invocation) throws Throwable {
    	// 获取属性解析器,即在ProxyTransactionManagementConfiguration容器配置类中注册事务拦截器时注入的
        TransactionAttributeSource tas = this.getTransactionAttributeSource();
        TransactionAttribute txAttr = tas != null ? tas.getTransactionAttribute(method, targetClass) : null;
        // 获取事务管理器(spring会先根据qualifier,即@Transactional注解的value属性去获取,一般都不配置。只要在容器中有注册过PlatformTransactionManager类型的事务管理器,就可以直接通过类型来获取;)
        TransactionManager tm = this.determineTransactionManager(txAttr);
        if (this.reactiveAdapterRegistry != null && tm instanceof ReactiveTransactionManager) {
            TransactionAspectSupport.ReactiveTransactionSupport txSupport = (TransactionAspectSupport.ReactiveTransactionSupport)this.transactionSupportCache.computeIfAbsent(method, (key) -> {
                if (KotlinDetector.isKotlinType(method.getDeclaringClass()) && TransactionAspectSupport.KotlinDelegate.isSuspend(method)) {
                    throw new TransactionUsageException("Unsupported annotated transaction on suspending function detected: " + method + ". Use TransactionalOperator.transactional extensions instead.");
                } else {
                    ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(method.getReturnType());
                    if (adapter == null) {
                        throw new IllegalStateException("Cannot apply reactive transaction to non-reactive return type: " + method.getReturnType());
                    } else {
                        return new TransactionAspectSupport.ReactiveTransactionSupport(adapter);
                    }
                }
            });
            return txSupport.invokeWithinTransaction(method, targetClass, invocation, txAttr, (ReactiveTransactionManager)tm);
        } else {
            PlatformTransactionManager ptm = this.asPlatformTransactionManager(tm);
            String joinpointIdentification = this.methodIdentification(method, targetClass, txAttr);
            if (txAttr != null && ptm instanceof CallbackPreferringPlatformTransactionManager) {
                TransactionAspectSupport.ThrowableHolder throwableHolder = new TransactionAspectSupport.ThrowableHolder();

                Object result;
                try {
                    result = ((CallbackPreferringPlatformTransactionManager)ptm).execute(txAttr, (statusx) -> {
                        TransactionAspectSupport.TransactionInfo txInfo = this.prepareTransactionInfo(ptm, txAttr, joinpointIdentification, statusx);

                        Object var9;
                        try {
                            Object retVal = invocation.proceedWithInvocation();
                            if (retVal != null && vavrPresent && TransactionAspectSupport.VavrDelegate.isVavrTry(retVal)) {
                                retVal = TransactionAspectSupport.VavrDelegate.evaluateTryFailure(retVal, txAttr, statusx);
                            }

                            var9 = retVal;
                            return var9;
                        } catch (Throwable var13) {
                            if (txAttr.rollbackOn(var13)) {
                                if (var13 instanceof RuntimeException) {
                                    throw (RuntimeException)var13;
                                }

                                throw new TransactionAspectSupport.ThrowableHolderException(var13);
                            }

                            throwableHolder.throwable = var13;
                            var9 = null;
                        } finally {
                            this.cleanupTransactionInfo(txInfo);
                        }

                        return var9;
                    });
                } catch (TransactionAspectSupport.ThrowableHolderException var20) {
                    throw var20.getCause();
                } catch (TransactionSystemException var21) {
                    if (throwableHolder.throwable != null) {
                        this.logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
                        var21.initApplicationException(throwableHolder.throwable);
                    }

                    throw var21;
                } catch (Throwable var22) {
                    if (throwableHolder.throwable != null) {
                        this.logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
                    }

                    throw var22;
                }

                if (throwableHolder.throwable != null) {
                    throw throwableHolder.throwable;
                } else {
                    return result;
                }
            } else {
                TransactionAspectSupport.TransactionInfo txInfo = this.createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);

                Object retVal;
                try {
                    retVal = invocation.proceedWithInvocation();
                } catch (Throwable var18) {
                	// 如果目标方法抛异常,会执行completeTransactionAfterThrowing,即回滚
                    this.completeTransactionAfterThrowing(txInfo, var18);
                    throw var18;
                } finally {
                    this.cleanupTransactionInfo(txInfo);
                }

                if (retVal != null && vavrPresent && TransactionAspectSupport.VavrDelegate.isVavrTry(retVal)) {
                    TransactionStatus status = txInfo.getTransactionStatus();
                    if (status != null && txAttr != null) {
                        retVal = TransactionAspectSupport.VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
                    }
                }
				
				// 进行事务提交
                this.commitTransactionAfterReturning(txInfo);
                return retVal;
            }
        }
    }

5.2 原理小结
  1. 在容器配置类上使用@EnableTransactionManagement注解,该注解在容器中注册了两大组件——AutoProxyRegistrar、ProxyTransactionManagementConfiguration。
  2. AutoProxyRegistrar通过导入方式在容器中注册了InfrastructureAdvisorAutoProxyCreator,即后置处理器。
  3. ProxyTransactionManagementConfiguration本身就是一个容器配置类,它注册了transactionAdvisor(事务增强器),然后又在这个事务增强器中注入了两个属性transactionAttributeSource、transactionInterceptor。
  4. transactionAttributeSource用于解析@Transactional注解的各种属性。
  5. transactionInterceptor实现了MethodInterceptor,是一个拦截器链,这个拦截器链会从容器中获取事务管理器,利用事务管理器,在目标方法发生异常时执行回滚,在目标发生正常完成后提交事务。
  6. 第2步的InfrastructureAdvisorAutoProxyCreator后置处理器,会在目标对象创建完成之后将其包装为代理对象,代理对象在执行目标方法时会首先获取拦截器链,这个拦截器链就是第5步的transactionInterceptor。
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值