事件管理在体系开辟中是不可缺少的一部分,Spring提供了很好事件管理机制
分类
重要分为编程式事件和声明式事件两种。
编程式事件
是指在代码中手动的管理事件的提交、回滚等操纵,代码侵入性比力强,如下示例:- try {
- //TODO something
- transactionManager.commit(status);
- } catch (Exception e) {
- transactionManager.rollback(status);
- throw new InvoiceApplyException("异常失败");
- }
复制代码 声明式事件
基于AOP面向切面的,它将具体业务与事件处置惩罚部分解耦,代码侵入性很低,所以在实际开辟中声明式事件用的比力多。声明式事件也有两种实现方式,一是基于TX和AOP的xml设置文件方式,第二种就是基于@Transactional注解了。- @Transactional
- @GetMapping("/test")
- public String test() {
- int insert = cityInfoDictMapper.insert(cityInfoDict);
- }
复制代码 事件传播方式propagation
Spring的传播特性(举动)指的是:当一个事件方法调用另一个事件方法时,事件该怎样进行。Spring的传播举动有七种,可以分为三大类类型。
场景:以下都会使用这个例子,方便明白;有A类内部有个a方法、B类内部有个b方法
支持当前事件
- REQUIRED:如果当前方法存在一个事件,则加入这个事件。若当前方法不存在事件,则新建一个事件。
例:b方法的传播特性是REQUIRED,当a方法调用到b方法时,若a方法存在事件,则b方法加入这个事件,与a共用一个事件。若a方法不存在事件,则b方法新建一个事件。回滚怎么判断:前者两个方法使用同一个事件,当a或者b任意一个方法出现异常,a和b都会回滚;后者a没有事件不会回滚,b方法有事件,会回滚。
- SUPPORTS:如果当前方法存在事件,则加入事件。反之,则以非事件方式运行。
例:b方法的传播特性是SUPPORTS,当a方法调用到b方法时,若a方法存在事件,则b方法加入这个事件。若a方法不存在事件,则b方法以非事件进行。
- MANDATORY:如果当前方法存在事件则加入事件,若不存在则抛出异常。
例:b方法的传播特性是MANDATORY,当a方法调用到b方法时,若a方法存在事件,则b方法加入这个事件。若a方法不存在事件,则抛出异常。
不支持当前事件
- REQUIRES_NEW:新建一个事件,如果当前方法存在事件,则把当前事件挂起。
例:b方法的传播特性是REQUIRES_NEW,当a方法调用到b方法时,b方法新建一个事件,如果a方法存在事件,则把a方法事件挂起。回滚怎么判断:要明白一点就是a和b的事件没有关系。当a没有事件时,只有b有事件,a方法不会回滚,b方法会回滚。后者a和b有不同事件,当b方法出现异常时b会回滚。而a方法会不会回滚需要分为两种环境:若b中的异常本身捕获则a不会回滚,若b中是是抛出异常,则a也会回滚。
- NOT_SUPPORTED:以非事件方式执行,若存在当前事件,则把当前事件挂起。
例:b方法的传播特性是NOT_SUPPORTED,当a方法调用到b方法时,b方法以非事件方式执行,若a方法存在事件,则挂起a方法事件。
- NEVER:以非事件方式执行,若存在当前事件,则会抛出异常。
例:b方法的传播特性是NEVER,当a方法调用到b方法时,b方法以非事件方式执行,若a方法存在事件,则抛出异常。
嵌套事件
NESTED:如果当前存在事件,则在嵌套事件内执行。如果当前没有事件,则执行与REQUIRED类似的操纵。
例:b方法的传播特性是NESTED,当a方法内调用到b方法时。若a方法存在事件,则在a方法内嵌套b方法的事件,两者是有联系的,b事件相当于a事件的子事件。若a方法不存在事件,则b方法新建一个事件。回滚怎么判断:前者a和b都有事件,并且是相关联的事件(a的事件相当于父事件、b的事件相当于子事件),当a方法出现异常时,a和b都会回滚。当b方法出现异常时则要分两种环境分析:若b中的异常本身捕获则a不会回滚,若b中是是抛出异常,则a也会回滚。
其他属性
isolation 属性:隔离级别
isolation :事件的隔离级别,默认值为 Isolation.DEFAULT。开辟中基本都是 default 级别
- Isolation.DEFAULT:使用底层数据库默认的隔离级别
- Isolation.READ_COMMITTED:读已提交
- Isolation.READ_UNCOMMITTED:读未提交
- Isolation.REPEATABLE_READ:可重复读
- Isolation.SERIALIZABLE:串行化
timeout 属性
timeout :事件的超时时间,。如果超过该时间限制但事件还没有完成,则自动回滚事件。默认值为 -1,默认不限制时间
readOnly 属性
readOnly :指定事件是否为只读事件,默认值为 false;为了忽略那些不需要事件的方法,好比读取数据,可以设置 read-only 为 true。
rollbackFor 属性
rollbackFor :用于指定能够触发事件回滚的异常类型,可以指定多个异常类型。
noRollbackFor属性
noRollbackFor:抛出指定的异常类型,不回滚事件,也可以指定多个异常类型。
@Transactional
作用范围
@Transactional 可以作用在接口、类、类方法。
- 作用于类:当把@Transactional 注解放在类上时,表示所有该类的public方法都设置雷同的事件属性信息。
- 作用于方法:当类设置了@Transactional,方法也设置了@Transactional,方法的事件会覆盖类的事件设置信息。
- 作用于接口:不推荐这种使用方法,因为一旦标注在Interface上并且设置了Spring AOP 使用CGLib动态代理,将会导致@Transactional注解失效
错误使用场景
无需事件的业务
在没有事件操纵的业务方法上使用 @Transactional 注解;
例如,在只有查询的操纵上,或者在只操纵单表的环境下 使用 @Transactional 注解。
- 固然对业务功能无影响,但从编码角度看是不规范的。其他开辟者大概会认为该方法实际需要事件支持,从而增加明白代码的复杂性。
- @Transactional是通过动态代理实现的,每次调用带有 @Transactional 注解的方法时,事件管理器都会检查是否需要启动一个新事件,造成性能开销。固然事件管理的开销在大多数当代数据库和应用服务器中相对较小,但仍旧存在。
- @Transactional
- public String testQuery() {
- standardBak2Service.getById(1L);
- return "testB";
- }
复制代码 事件范围过大
有些同学为了省事直接将 @Transactional 注解加在了类上或者抽象类上,这样做导致的题目就是类内的方法或抽象类的实现类中所有方法全部都被事件管理。增加了不必要的性能开销或复杂性,发起按需使用,只在有事件逻辑的方法上加@Transactional。
以下是事件范围过大大概引发的题目及其相关处置惩罚发起:
- 锁竞争:事件范围过大大概会导致较长时间持有数据库锁,从而增加锁竞争的大概性。其他事件在等待锁开释期间,大概会导致响应时间变长或出现超时。
- 死锁:长时间持有锁的事件增加了死锁的风险。当多个事件相互持有对方需要的资源时,大概会陷入死锁状态。
失效场景
应用在非 public 修饰的方法上
之所以会失效是因为@Transactional 注解依赖于Spring AOP切面来增强事件举动,这个 AOP 是通过代理来实现的
而无论是JDK动态代理还是CGLIB代理,Spring AOP的默认举动都是只代理public方法。
被用 final 、static 修饰方法
和上边的原因类似,被用 final 、static 修饰的方法上加 @Transactional 也不会生效。
- static 静态方法属于类本身的而非实例,因此代理机制是无法对静态方法进行代理或拦截的
- final 修饰的方法不能被子类重写,事件相关的逻辑无法插入到 final 方法中,代理机制无法对 final 方法进行拦截或增强。
同类中非事件方法调用事件方法
好比有一个类Test,它的一个方法A,A再调用本类的方法B(不论方法B是用public还是private修饰),但方法A没有声明注解事件,而B方法有。则外部调用方法A之后,方法B的事件是不会起作用的。但是如果是A声明了事件,A的事件是会生效的。
失效原因:事件是基于动态代理实现的,但本类中调用另一个方法默认是this调用关系,并非动态代理,故失效
解决方案:要么将操纵移动到事件中,要么调用另一个Service中的事件方法
Bean 未被 spring 管理
上边我们知道 @Transactional 注解通过 AOP 来管理事件,而 AOP 依赖于代理机制。因此,Bean 必须由Spring管理实例! 要确保为类加上如 @Controller、@Service 或 @Component注解,让其被Spring所管理,这很轻易忽视。
异步线程调用
如果我们在 testMerge() 方法中使用异步线程执行事件操纵,通常也是无法成功回滚的,来个具体的例子。
假设testMerge() 方法在事件中调用了 testA(),testA() 方法中开启了事件。接着,在 testMerge() 方法中,我们通过一个新线程调用了 testB(),testB() 中也开启了事件,并且在 testB() 中抛出了异常。此时,testA() 不会回滚 和 testB() 回滚。
testA() 无法回滚是因为没有捕获到新线程中 testB()抛出的异常;testB()方法正常回滚。
在多线程环境下,Spring 的事件管理器不会跨线程传播事件,事件的状态(如事件是否已开启)是存储在线程本地的 ThreadLocal 来存储和管理事件上下文信息。这意味着每个线程都有一个独立的事件上下文,事件信息在不同线程之间不会共享。
- @Transactional
- public void transactionalMethod() {
- new Thread(() ->{
- Valuation v = new Valuation();
- v.setUserName("张三");
- valuationMapper.insert(v);
- }).start();
- }
复制代码 Spring的事件是通过数据库连接来实现不同线程使用不同的数据库连接,且放在ThreadLocal中,基于同一个数据库连接的事件才能同时提交或回滚,多线程场景下,拿到的数据库连接不是同一个
解决方案:
数据库引擎不支持事件
事件能否生效数据库引擎是否支持事件是关键。常用的MySQL数据库默认使用支持事件的innodb引擎。一旦数据库引擎切换成不支持事件的myisam,那事件就从根本上失效了。
propagation 设置错误
如果错误的设置以下三种 propagation,事件将不会发生回滚。
- TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事件,则加入该事件;如果当前没有事件,则以非事件的方式继承运行。
- TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事件方式运行,如果当前存在事件,则把当前事件挂起。
- TransactionDefinition.PROPAGATION_NEVER:以非事件方式运行,如果当前存在事件,则抛出异常。
rollbackFor 设置错误
rollbackFor 可以指定能够触发事件回滚的异常类型。Spring 默认抛出了未检查unchecked异常(继承自 RuntimeException 的异常)或者 Error才回滚事件;其他异常(如IOException)不会触发回滚事件。如果在事件中抛出其他类型的异常,例如 checked exceptions(检查型异常),但却期望 Spring 能够回滚事件,就需要指定 rollbackFor属性。
失效原因:@Transactional 注解默认处置惩罚RuntimeException,即只有抛出运行时异常,才会触发事件回滚
解决方案:@Transactional 设置为 @Transactional(rollbackFor =Exception.class) 或者直接抛出运行时异常
异常被 catch了
spring的事件是在调用业务方法之前开始的,业务方法执行完毕之后才执行commit or rollback,事件是否执行取决于是否抛出runtime异常。如果抛出runtime exception 并在你的业务方法中没有catch到的话,事件会回滚。
在业务方法中一般不需要catch异常,如果非要catch肯定要抛出throw new RuntimeException(),或者注解中指定抛异常类型@Transactional(rollbackFor=Exception.class),否则会导致事件失效,数据commit造成数据不同等,所以有些时间try catch反倒会画蛇添足。
嵌套事件题目
还有一种场景就是嵌套事件题目,好比,我们在 testMerge() 方法中调用了事件方法 testA() 和事件方法 testB(),此时不希望 testB() 抛出异常让整个 testMerge() 都跟着回滚;这就需要单独 try catch 处置惩罚 testB() 的异常,不让异常在向上抛。- @RequiredArgsConstructor
- @Slf4j
- @Service
- public class TestMergeService {
- private final TestBService testBService;
- private final TestAService testAService;
- @Transactional
- public String testMerge() {
-
- testAService.testA();
- try {
- testBService.testB();
- } catch (Exception e) {
- log.error("testMerge error:{}", e);
- }
- return "ok";
- }
- }
- @Service
- public class TestAService {
- @Transactional
- public String testA() {
- standardBakService.save(entity);
- return "ok";
- }
- }
- @Service
- public class TestBService {
- @Transactional
- public String testB() {
- standardBakService.save(entity2);
-
- throw new RuntimeException("test2");
- }
- }
复制代码 源码分析
以下源码均基于Spring4.3.12版本。重要从 创建事件、开启事件、提交事件、事件回滚 的维度来详细分析声明式事件。
事件简易流程图
代理类生成
在Spring框架中,当设置了事件管理器并声明了@Transactional注解时,Spring会在实例化bean时生成事件增强的代理类。创建代理类参考源码路径如下:- AbstractAutowireCapableBeanFactory.createBean=>
- doCreateBean()=>
- initializeBean()=>
- applyBeanPostProcessorsAfterInitialization()=>
- postProcessAfterInitialization()(BeanPostProcessor内接口)=>
- AbstractAutoProxyCreator.postProcessAfterInitialization()=>
- wrapIfNecessary()=>
- createProxy() 中 proxyFactory.setProxyTargetClass(true); //是否对类进行代理的设置,true为cglib代理
复制代码 代理类中方法执行入口
从TransactionInterceptor.invoke()方法开始分析 (获代替理类,调用父类TransactionAspectSupport.invokeWithinTransaction()方法,该方法会将代理类的方法纳入事件中)。- public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {
- public Object invoke(final MethodInvocation invocation) throws Throwable {
- // 返回代理类的目标类
- Class<?> targetClass = invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null;
- //事务中执行被代理的方法
- return this.invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {
- public Object proceedWithInvocation() throws Throwable {
- <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> return invocation.proceed();
- }
- });
- }
- }
复制代码 重要核心逻辑
TransactionAspectSupport.invokeWithinTransaction()方法负责获取事件属性和事件管理器,然后针对声明式事件和编程式事件区分处置惩罚流程(此处源码忽略编程式事件)。- protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final TransactionAspectSupport.InvocationCallback invocation) throws Throwable {
- // 获取事务属性 TransactionDefinition对象(回顾规则,隔离级别,只读等)
- final TransactionAttribute txAttr = this.getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
- // 根据事务属性和方法,获取对应的事务管理器,(后续用于做事务的提交,回滚等操作),数据库的一些信息,
- final PlatformTransactionManager tm = this.determineTransactionManager(txAttr);
- // 获取事务方法全路径,
- final String joinpointIdentification = this.methodIdentification(method, targetClass, txAttr);
- //响应式编程事务,大多数情况下都会执行到 else中的语句;
- // CallbackPreferringPlatformTransactionManager 可以通过回掉函数来处理事务的提交和回滚操作, 此处不考虑,此处源码可以忽略
- if (txAttr != null && tm instanceof CallbackPreferringPlatformTransactionManager) {
- // 此处省略,此处为编程式事务 处理逻辑
- } else {
- //创建事务,事务属性等信息会被保存进 TransactionInfo,便于后续流程中的提交和回滚操作,详情见下文
- TransactionAspectSupport.TransactionInfo txInfo = this.createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
- Object retVal = null;
- try {
- <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> // 执行目标的方法 (执行具体的业务逻辑)
- <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> retVal = invocation.proceedWithInvocation();
- } catch (Throwable var15) {
- <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> //异常处理
- <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> this.completeTransactionAfterThrowing(txInfo, var15);
- <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> throw var15;
- } finally {
- <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> //清除当前节点的事务消息,将旧事务节点消息通过ThreadLoacl更新到当前线程(事务的挂起操作就是在这执行)
- <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> this.cleanupTransactionInfo(txInfo);
- }
- //提交事务
- this.commitTransactionAfterReturning(txInfo);
- return retVal;
- }
- }
-
复制代码 开启事件
TransactionAspectSupport.createTransactionIfNecessary() 方法作用是检查当前是否存在事件,如果存在,则根据肯定的规则创建一个新的事件。- protected TransactionAspectSupport.TransactionInfo createTransactionIfNecessary(PlatformTransactionManager tm, TransactionAttribute txAttr, final String joinpointIdentification) {
- //如果事务名称不为空,则使用方法唯一标识。并使用 DelegatingTransactionAttribute 封装 txAttr
- if (txAttr != null && ((TransactionAttributerollbackOn)txAttr).getName() == null) {
- txAttr = new DelegatingTransactionAttribute((TransactionAttribute)txAttr) {
- <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> public String getName() {
- <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> return joinpointIdentification;
- <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> }
- };
- }
- TransactionStatus status = null;
- if (txAttr != null) {
- if (tm != null) {
- <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> // 获取事务状态。内部判断是否开启事务绑定线程与数据库连接。详情见下文
- <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> status = tm.getTransaction((TransactionDefinition)txAttr);
- } else if (this.logger.isDebugEnabled()) {
- <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> this.logger.debug("Skipping transactional joinpoint [" + joinpointIdentification + "] because no transaction manager has been configured");
- }
- }
- //构建事务消息,根据指定的属性与状态status 构建一个 TransactionInfo。将已经建立连接的事务所有信息,都记录在ThreadLocal下的TransactionInfo 实例中,包括目标方法的所有状态信息,如果事务执行失败,spring会根据TransactionInfo中的信息来进行回滚等后续操作
- return this.prepareTransactionInfo(tm, (TransactionAttribute)txAttr, joinpointIdentification, status);
- }
复制代码 获取当前事件对象
AbstractPlatformTransactionManager.getTransaction() 获取当前事件对象。通过这个方法,可以获取到关于事件的详细信息,如事件的状态、相关属性等。- public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
- throws TransactionException {
-
- //definition 中存储的事务的注解信息,超时时间和隔离级别等
- TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());
- // 获取当前事务
- Object transaction = doGetTransaction();
- boolean debugEnabled = logger.isDebugEnabled();
- // 判断当前线程是否存在事务
- if (isExistingTransaction(transaction)) {
- // 处理已经存在的事务
- return handleExistingTransaction(def, transaction, debugEnabled);
- }
- // 事务超时设置验证,超时时间小于-1 抛异常
- if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
- throw new InvalidTimeoutException("Invalid transaction timeout", def.getTimeout());
- }
- // 如果当前线程不存在事务且 事务传播行为是 MANDATORY(用当前事务,如果当前没有事务,则抛出异常) 抛异常
- if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
- throw new IllegalTransactionStateException(
- "No existing transaction found for transaction marked with propagation 'mandatory'");
- }
- //以下三种事务传播行为 需要开启新事务
- else if (def.getPropagationBehavior() == TransactionDefinition.propagation_required ||
- def.getPropagationBehavior() == TransactionDefinition.propagation_requires_new ||
- def.getPropagationBehavior() == TransactionDefinition.propagation_nested) {
- //挂起原事务,因为这里不存在原事务 故设置为null。
- //当一个事务方法内部调用了另一个事务方法时,如果第二个事务方法需要独立于第一个事务方法,那么可以使用 suspend 方法来挂起当前事务,然后再开始一个新的事务
- AbstractPlatformTransactionManager.SuspendedResourcesHolder suspendedResources = this.suspend((Object)null);
- try {
- <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> boolean newSynchronization = this.getTransactionSynchronization() != 2;
- <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> DefaultTransactionStatus status = this.newTransactionStatus((TransactionDefinition)definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
- <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> //开启事务
- <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> this.doBegin(transaction, (TransactionDefinition)definition);
- <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> //同步事务状态及书屋属性
- <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> this.prepareSynchronization(status, (TransactionDefinition)definition);
- <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> return status;
- } catch (RuntimeException var7) {
- <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> this.resume((Object)null, suspendedResources);
- <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> throw var7;
- }
- }
- else {
- boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);//0
- //创建默认状态 详情见 下文
- return prepareTransactionStatus(def, null, true, newSynchronization, debugEnabled, null);
- }
- }
复制代码 执行获取事件的具体操纵
AbstractPlatformTransactionManager.doGetTransaction() 方法用于执行获取事件的具体操纵。它大概会根据一些条件或规则,去查找和获取当前的事件对象,并进行相应的处置惩罚。- protected Object doGetTransaction() {
- DataSourceTransactionManager.DataSourceTransactionObject txObject = new DataSourceTransactionManager.DataSourceTransactionObject();
- //是否允许在一个事务内部开启另一个事务。
- txObject.setSavepointAllowed(this.isNestedTransactionAllowed());
- // this.dataSource数据源 配置
- //判断当前线程如果已经记录数据库连接则使用原连接
- ConnectionHolder conHolder = (ConnectionHolder)TransactionSynchronizationManager.getResource(this.dataSource);
- //false 表示不是新创建连接
- txObject.setConnectionHolder(conHolder, false);
- return txObject;
- }
复制代码
- this.dataSource() 是我们设置DataSourceTransactionManager时传入的。
- <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean>
复制代码
- TransactionSynchronizationManager.getResource() 方法的作用重要是获取与当前事件相关联的资源。TransactionSynchronizationManager 持有一个ThreadLocal的实例,存在一个key为dataSource ,value为ConnectionHolder 的Map信息。
- //ThreadLocal 存放 ConnectionHolder 信息,ConnectionHolder 可以明白为Connection(数据库连接)的包装类,其中最重要属性为 Connectionprivate static final ThreadLocal resources = new NamedThreadLocal("Transactional resources"); // 获取ConnectionHolder public static Object getResource(Object key) { Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key); //获取连接信息 Object value = doGetResource(actualKey); return value; } //具体执行获取连接信息操纵 private static Object doGetResource(Object actualKey) { //从 ThreadLoacl中获取 Map map = (Map)resources.get(); if (map == null) { return null; } else { Object value = map.get(actualKey); if (value instanceof ResourceHolder && ((ResourceHolder)value).isVoid()) { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> map.remove(actualKey); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> if (map.isEmpty()) { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> resources.remove(); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> } <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> value = null; } return value; } }
复制代码 判断是否存在正在进行的事件
AbstractPlatformTransactionManager.isExistingTransaction() 方法用于判断是否存在正在进行的事件。它可以帮助我们确定当前的执行环境是否处于事件中,以便进行相应的处置惩罚。- protected boolean isExistingTransaction(Object transaction) {
- DataSourceTransactionManager.DataSourceTransactionObject txObject = (DataSourceTransactionManager.DataSourceTransactionObject)transaction;
- return txObject.getConnectionHolder() != null && txObject.getConnectionHolder().isTransactionActive();
- }
复制代码 挂起事件
AbstractPlatformTransactionManager.suspend() 挂起事件,对有无同步的事件接纳不同方案,doSuspend()执行挂起具体操纵。- protected final AbstractPlatformTransactionManager.SuspendedResourcesHolder suspend(Object transaction) throws TransactionException { //如果有同步的事件,则优先挂起同步事件 if (TransactionSynchronizationManager.isSynchronizationActive()) { List suspendedSynchronizations = this.doSuspendSynchronization(); try { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> Object suspendedResources = null; <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> if (transaction != null) { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> //执行挂起操纵 <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> suspendedResources = this.doSuspend(transaction); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> } <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> //重置事件名称 <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> String name = TransactionSynchronizationManager.getCurrentTransactionName(); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> TransactionSynchronizationManager.setCurrentTransactionName((String)null); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> //重置只读状态 <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly(); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> TransactionSynchronizationManager.setCurrentTransactionReadOnly(false); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> //重置隔离级别 <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> Integer isolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel(); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> TransactionSynchronizationManager.setCurrentTransactionIsolationLevel((Integer)null); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> //重置事件激活状态 <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> boolean wasActive = TransactionSynchronizationManager.isActualTransactionActive(); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> TransactionSynchronizationManager.setActualTransactionActive(false); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> //返回挂起的事件 <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> return new AbstractPlatformTransactionManager.SuspendedResourcesHolder(suspendedResources, suspendedSynchronizations, name, readOnly, isolationLevel, wasActive); } catch (RuntimeException var8) { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> this.doResumeSynchronization(suspendedSynchronizations); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> throw var8; } } else if (transaction != null) { Object suspendedResources = this.doSuspend(transaction); return new AbstractPlatformTransactionManager.SuspendedResourcesHolder(suspendedResources); } else { return null; } }
复制代码
- AbstractPlatformTransactionManager.doSuspend()执行挂起操纵只是将当前ConnectionHolder设置为null,返回原有事件消息,方便后续恢复原有事件消息,并将当前正在进行的事件信息进行重置。
- protected Object doSuspend(Object transaction) {
- DataSourceTransactionManager.DataSourceTransactionObject txObject = (DataSourceTransactionManager.DataSourceTransactionObject)transaction;
- txObject.setConnectionHolder((ConnectionHolder)null);
- //接触绑定
- return TransactionSynchronizationManager.unbindResource(this.dataSource);
- }
- //解除绑定操作,将现有的事务消息remove并返回上一级
- public static Object unbindResource(Object key) throws IllegalStateException {
- Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
- //解绑操作,移除资源
- Object value = doUnbindResource(actualKey);
- if (value == null) {
- throw new IllegalStateException("No value for key [" + actualKey + "] bound to thread [" + Thread.currentThread().getName() + "]");
- } else {
- return value;
- }
- }
复制代码
- AbstractPlatformTransactionManager.doBegin()数据库连接获取,当新事件时,则获取新的数据库连接,并为其设置隔离级别,是否只读等属性。
- protected void doBegin(Object transaction, TransactionDefinition definition) { DataSourceTransactionManager.DataSourceTransactionObject txObject = (DataSourceTransactionManager.DataSourceTransactionObject)transaction; Connection con = null; try { //新事件开启时将 ConnectionHolder 设置为null if (txObject.getConnectionHolder() == null || txObject.getConnectionHolder().isSynchronizedWithTransaction()) { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> //获取新的数据库连接 <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> Connection newCon = this.dataSource.getConnection(); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> txObject.setConnectionHolder(new ConnectionHolder(newCon), true); } txObject.getConnectionHolder().setSynchronizedWithTransaction(true); con = txObject.getConnectionHolder().getConnection(); //设置事件隔离级别 和readOnly属性 Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition); txObject.setPreviousIsolationLevel(previousIsolationLevel); if (con.getAutoCommit()) { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> txObject.setMustRestoreAutoCommit(true); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> // 交给Spring控制事件提交 <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> con.setAutoCommit(false); } this.prepareTransactionalConnection(con, definition); //设置当前线程的事件激活状态 txObject.getConnectionHolder().setTransactionActive(true); int timeout = this.determineTimeout(definition); if (timeout != -1) { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> // 设置超时时间 <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> txObject.getConnectionHolder().setTimeoutInSeconds(timeout); } if (txObject.isNewConnectionHolder()) { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> TransactionSynchronizationManager.bindResource(this.getDataSource(), txObject.getConnectionHolder()); } } catch (Throwable var7) { if (txObject.isNewConnectionHolder()) { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> DataSourceUtils.releaseConnection(con, this.dataSource); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> txObject.setConnectionHolder((ConnectionHolder)null, false); } throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", var7); } }
复制代码
- AbstractPlatformTransactionManager.prepareTransactionStatus()创建默认Status,如果不需要开始事件 (好比SUPPORTS),则返回一个默认的状态。
- protected final DefaultTransactionStatus prepareTransactionStatus(TransactionDefinition definition, Object transaction, boolean newTransaction, boolean newSynchronization, boolean debug, Object suspendedResources) {
- DefaultTransactionStatus status = this.newTransactionStatus(definition, transaction, newTransaction, newSynchronization, debug, suspendedResources);
- this.prepareSynchronization(status, definition);
- return status;
- }
-
- protected DefaultTransactionStatus newTransactionStatus(TransactionDefinition definition, Object transaction, boolean newTransaction, boolean newSynchronization, boolean debug, Object suspendedResources) {
- boolean actualNewSynchronization = newSynchronization && !TransactionSynchronizationManager.isSynchronizationActive();
- //创建 DefaultTransactionStatus 对象
- return new DefaultTransactionStatus(transaction, newTransaction, actualNewSynchronization, definition.isReadOnly(), debug, suspendedResources);
- }
复制代码
- AbstractPlatformTransactionManager.handleExistingTransaction()针对不同的传播举动做不同的处置惩罚方法,好比挂起原事件开启新事件等等。
- private TransactionStatus handleExistingTransaction(TransactionDefinition definition, Object transaction, boolean debugEnabled) throws TransactionException { //当传播举动是 NEVER 时抛出异常 if (definition.getPropagationBehavior() == 5) { throw new IllegalTransactionStateException("Existing transaction found for transaction marked with propagation 'never'"); } else { AbstractPlatformTransactionManager.SuspendedResourcesHolder suspendedResources; boolean newSynchronization; //当传播方式为NOT_SUPPORTED 时挂起当前事件,然后在无事件的状态下运行 if (definition.getPropagationBehavior() == 4) { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> //挂起事件 <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> suspendedResources = this.suspend(transaction); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> newSynchronization = this.getTransactionSynchronization() == 0; <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> //返回默认status <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> return this.prepareTransactionStatus(definition, (Object)null, false, newSynchronization, debugEnabled, suspendedResources); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> //当传播方式为REQUIRES_NEW时,挂起当前事件,然后启动新事件 } else if (definition.getPropagationBehavior() == 3) { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> //挂起原事件 <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> suspendedResources = this.suspend(transaction); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> try { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> newSynchronization = this.getTransactionSynchronization() != 2; <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> DefaultTransactionStatus status = this.newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, suspendedResources); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> //启动新的事件 <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> this.doBegin(transaction, definition); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> this.prepareSynchronization(status, definition); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> return status; <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> } catch (Error|RuntimeException var7) { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> this.resumeAfterBeginException(transaction, suspendedResources, var7); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> throw var7; <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> } <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean>} else { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> boolean newSynchronization; <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> //当传播方式为NESTED时,设置事件的生存点 <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> //存在事件,将该事件标注生存点,形成嵌套事件 <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> //嵌套事件中的子事件出现异常不会影响到父事件生存点之前的操纵 <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> if (definition.getPropagationBehavior() == 6) { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> if (!this.isNestedTransactionAllowed()) { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> throw new NestedTransactionNotSupportedException("Transaction manager does not allow nested transactions by default - specify 'nestedTransactionAllowed' property with value 'true'"); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> } else { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> if (this.useSavepointForNestedTransaction()) { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> DefaultTransactionStatus status = this.prepareTransactionStatus(definition, transaction, false, false, debugEnabled, (Object)null); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> //创建生存点,回滚时,只回滚到该生存点 <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> status.createAndHoldSavepoint(); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> return status; <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> } else { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> newSynchronization = this.getTransactionSynchronization() != 2; <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> DefaultTransactionStatus status = this.newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, (Object)null); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> //如果不支持生存点,就启动新的事件 <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> this.doBegin(transaction, definition); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> this.prepareSynchronization(status, definition); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> return status; <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> } <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> } <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> } else { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> newSynchronization = this.getTransactionSynchronization() != 2; <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> return this.prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, (Object)null); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> } } } }
复制代码 回滚事件
TransactionAspectSupport.completeTransactionAfterThrowing() 判断事件是否存在,如不存在就不需要回滚,如果存在则在判断是否满意回滚条件。- protected void completeTransactionAfterThrowing(TransactionAspectSupport.TransactionInfo txInfo, Throwable ex) { //判断是否存在事件 if (txInfo != null && txInfo.hasTransaction()) { // 判断是否满意回滚条件。抛出的异常类型,和定义的回滚规则进行匹配 if (txInfo.transactionAttribute.rollbackOn(ex)) { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> try { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> // 回滚处置惩罚 <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus()); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> } <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean>//省略代码 } else { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> try { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> //不满意回滚条件 出现异常 <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> txInfo.getTransactionManager().commit(txInfo.getTransactionStatus()); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> } <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean>//省略代码 } } }
复制代码 AbstractPlatformTransactionManager.rollback()当在事件执行过程中出现异常或其他需要回滚的环境时,就会调用这个方法,将事件进行回滚操纵,撤销之前所做的数据库操纵,以保证数据的同等性。- public final void rollback(TransactionStatus status) throws TransactionException {
- //判断事务是否已经完成,回滚时抛出异常
- if (status.isCompleted()) {
- throw new IllegalTransactionStateException("Transaction is already completed - do not call commit or rollback more than once per transaction");
- } else {
- DefaultTransactionStatus defStatus = (DefaultTransactionStatus)status;
- // 执行回滚操作。
- this.processRollback(defStatus);
- }
- }
复制代码 AbstractPlatformTransactionManager.processRollback()方法重要用于处置惩罚事件的回滚操纵。通过这个方法,可以确保事件在需要回滚时能够精确地执行回滚操纵,保持数据的完整性。- private void processRollback(DefaultTransactionStatus status) { try { try { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> //解绑线程和会话绑定关系 <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> this.triggerBeforeCompletion(status); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> if (status.hasSavepoint()) { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> //如果有生存点(当前事件为单独的线程则会退到生存点) <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> status.rollbackToHeldSavepoint(); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> } else if (status.isNewTransaction()) { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> //如果是新事件直接回滚。调用数据库连接并调用rollback方法进行回滚。使用底层数据库连接提供的API <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> this.doRollback(status); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> } else if (status.hasTransaction()) { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> if (status.isLocalRollbackOnly() || !this.isGlobalRollbackOnParticipationFailure()) { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> //如果当前事件不是独立的事件,则只能等待事件链执行完成后再做回滚操纵 <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> this.doSetRollbackOnly(status); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> } <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> } <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean>} <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean>//catch 等代码 // 关闭会话,重置属性 this.triggerAfterCompletion(status, 1); } finally { //清理并恢复挂起的事件 this.cleanupAfterCompletion(status); } }
复制代码 提交事件
TransactionAspectSupport.commitTransactionAfterReturning() 基本上和回滚一样,都是先判断是否有事件,在操纵提交。- protected void commitTransactionAfterReturning(TransactionAspectSupport.TransactionInfo txInfo) {
- if (txInfo != null && txInfo.hasTransaction()) {
- //提交事务
- txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
- }
- }
复制代码 AbstractPlatformTransactionManager.commit() 创建默认Status prepareTransactionStatu,发现是否有回滚标志,然后进行回滚。如果判断无需回滚就可以直接提交。- public final void commit(TransactionStatus status) throws TransactionException { // 事件状态已完成则抛异常 if (status.isCompleted()) { throw new IllegalTransactionStateException("Transaction is already completed - do not call commit or rollback more than once per transaction"); } else { DefaultTransactionStatus defStatus = (DefaultTransactionStatus)status; //发现回滚标志 if (defStatus.isLocalRollbackOnly()) { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> //回滚 <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> this.processRollback(defStatus); } else if (!this.shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> //回滚 <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> this.processRollback(defStatus); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> if (status.isNewTransaction() || this.isFailEarlyOnGlobalRollbackOnly()) { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> throw new UnexpectedRollbackException("Transaction rolled back because it has been marked as rollback-only"); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> } } else { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> // 提交操纵 <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> this.processCommit(defStatus); } } }
复制代码 AbstractPlatformTransactionManager.processCommit()处置惩罚事件的提交操纵- private void processCommit(DefaultTransactionStatus status) throws TransactionException { try { boolean beforeCompletionInvoked = false; try { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> this.prepareForCommit(status); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> this.triggerBeforeCommit(status); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> this.triggerBeforeCompletion(status); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> beforeCompletionInvoked = true; <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> boolean globalRollbackOnly = false; <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> if (status.isNewTransaction() || this.isFailEarlyOnGlobalRollbackOnly()) { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> globalRollbackOnly = status.isGlobalRollbackOnly(); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> } <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> if (status.hasSavepoint()) { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> //开释生存点信息 <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> status.releaseHeldSavepoint(); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> } else if (status.isNewTransaction()) { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> // 是一个新的事件 则提交。 获取数据库连接后使用数据库API进行提交事件 <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> this.doCommit(status); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> } <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> if (globalRollbackOnly) { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> throw new UnexpectedRollbackException("Transaction silently rolled back because it has been marked as rollback-only"); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> } } catch (TransactionException var20) { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> if (this.isRollbackOnCommitFailure()) { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> //提交异常回滚 <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> this.doRollbackOnCommitException(status, var20); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> } else { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> this.triggerAfterCompletion(status, 2); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> } <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> throw var20; } <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean>//省略其它异常拦截 try { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> this.triggerAfterCommit(status); } finally { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> this.triggerAfterCompletion(status, 0); } } finally { // 清理事件消息 this.cleanupAfterCompletion(status); } }
复制代码 扫除事件信息
AbstractPlatformTransactionManager.cleanupAfterCompletion() 这个方法重要用于在事件完成后进行清理工作。它会负责开释资源、清理临时数据等,以确保体系处于良好的状态。- private void cleanupAfterCompletion(DefaultTransactionStatus status) {
- //将当前事务设置为完成状态
- status.setCompleted();
- if (status.isNewSynchronization()) {
- // 清空当前事务消息
- TransactionSynchronizationManager.clear();
- }
- if (status.isNewTransaction()) {
- //如果是新事务 则在事务完成之后做清理操作
- this.doCleanupAfterCompletion(status.getTransaction());
- }
- if (status.getSuspendedResources() != null) {
- // 将原事务从挂起状态恢复
- this.resume(status.getTransaction(), (AbstractPlatformTransactionManager.SuspendedResourcesHolder)status.getSuspendedResources());
- }
- }
复制代码 AbstractPlatformTransactionManager.doCleanupAfterCompletion()在新事件完成后会调用resetConnectionAfterTransaction方法重置数据库连接信息,并判断如果是新的数据库连接则将其放回连接池。- protected void doCleanupAfterCompletion(Object transaction) {
- DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
- if (txObject.isNewConnectionHolder()) {
- // 将数据库连接从当前线程中解除绑定
- TransactionSynchronizationManager.unbindResource(this.dataSource);
- }
- Connection con = txObject.getConnectionHolder().getConnection();
- try {
- // 恢复数据库连接的autoCommit状态
- if (txObject.isMustRestoreAutoCommit()) {
- con.setAutoCommit(true);
- }
- // 负责重置数据库连接信息,包括隔离级别、readOnly属性等
- DataSourceUtils.resetConnectionAfterTransaction(con, txObject.getPreviousIsolationLevel());
- }
- catch (Throwable ex) {
- logger.debug("Could not reset JDBC Connection after transaction", ex);
- }
- if (txObject.isNewConnectionHolder()) {
- // 如果是新的数据库连接则将数据库连接放回连接池
- DataSourceUtils.releaseConnection(con, this.dataSource);
- }
- txObject.getConnectionHolder().clear();
- }
复制代码 AbstractPlatformTransactionManager.resume() 如果事件执行前有事件挂起,那么当前事件执行竣过后需要将挂起的事件恢复,挂起事件时生存了原事件信息,重置了当前事件信息,所以恢复操纵就是将当前的事件信息设置为之前生存的原事件信息。- protected final void resume(Object transaction, AbstractPlatformTransactionManager.SuspendedResourcesHolder resourcesHolder) throws TransactionException { if (resourcesHolder != null) { Object suspendedResources = resourcesHolder.suspendedResources; if (suspendedResources != null) { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> // 执行 恢复挂起事件 ,绑定资源bindResource <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> this.doResume(transaction, suspendedResources); } List suspendedSynchronizations = resourcesHolder.suspendedSynchronizations; if (suspendedSynchronizations != null) { <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> TransactionSynchronizationManager.setActualTransactionActive(resourcesHolder.wasActive); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(resourcesHolder.isolationLevel); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> TransactionSynchronizationManager.setCurrentTransactionReadOnly(resourcesHolder.readOnly); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> TransactionSynchronizationManager.setCurrentTransactionName(resourcesHolder.name); <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean> this.doResumeSynchronization(suspendedSynchronizations); } } }
复制代码 TransactionAspectSupport.cleanupTransactionInfo()扫除当前节点的事件消息,将往事件节点信息通过thradLoacl更新到当前线程。- protected void cleanupTransactionInfo(TransactionAspectSupport.TransactionInfo txInfo) { if (txInfo != null) { //从当前线程的 ThreadLocal 获取上层的事件信息,将当前事件出栈,继承执行上层事件 txInfo.restoreThreadLocalStatus(); } } private void restoreThreadLocalStatus() { //当前事件处置惩罚完之后,恢复上层事件上下文 <bean id="valuationTransactionManager" >
- <property name="dataSource" ref="valuationDataSource"/>
- </bean>TransactionAspectSupport.transactionInfoHolder.set(this.oldTransactionInfo); }
复制代码 小结
如果方法正常执行完成且没有异常,调用commitTransactionAfterReturning()方法。如果执行中出现异常,调用completeTransactionAfterThrowing()方法。
两个方法内部都会判断是否存在事件以及是否满意回滚条件来决定终极执行提交操纵还是回滚操纵。
口试题专栏
Java口试题专栏已上线,欢迎访问。
- 如果你不知道简历怎么写,简历项目不知道怎么包装;
- 如果简历中有些内容你不知道该不该写上去;
- 如果有些综合性题目你不知道怎么答;
那么可以私信我,我会尽我所能帮助你。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |