关于TransactionInterceptor类的解析,将是对spring-tx模块最重要的解析,该类是spring事务模块核心框架代码

TransactionInterceptor继承了TransactionAspectSupport类,所以有一个较为重要的静态方法,该方法由ThreadLocal实现,所以在任何地方都可以获取当前线程的TransactionStatus

public static TransactionStatus currentTransactionStatus()

第一步:首先,有一个类,类的全限定名是org.springframework.aop.framework.CglibAopProxy,而该类里面有一个内部类,是CglibMethodInvocation,该内部类签名如下

private static class CglibMethodInvocation extends ReflectiveMethodInvocation

这个内部类继承了ReflectiveMethodInvocation,但是这个内部是私有的,且该类是spring-tx模块至关重要的类,为了阐述spring-tx,要用到这个类,为此,需要我们自己新建一个类,并且将内部类CglibMethodInvocation的代码,全部都复制出来,将其修饰符改成public,方便我们自己使用,代码如下


import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.List;import org.springframework.aop.framework.ReflectiveMethodInvocation;
import org.springframework.aop.support.AopUtils;
import org.springframework.cglib.proxy.MethodProxy;
import org.springframework.lang.Nullable;
import org.springframework.util.ReflectionUtils;
/*** 这个类与CglibAopProxy.CglibMethodInvocation类内容完全一模一样* 只不过修饰符是public,为了方便我自己使用*/
public class MysCglibMethodInvocation extends ReflectiveMethodInvocation {@Nullableprivate final MethodProxy methodProxy;public MysCglibMethodInvocation(Object proxy, @Nullable Object target, Method method,Object[] arguments, @Nullable Class<?> targetClass,List<Object> interceptorsAndDynamicMethodMatchers, MethodProxy methodProxy) {super(proxy, target, method, arguments, targetClass, interceptorsAndDynamicMethodMatchers);// Only use method proxy for public methods not derived from java.lang.Objectthis.methodProxy = (Modifier.isPublic(method.getModifiers()) &&method.getDeclaringClass() != Object.class && !AopUtils.isEqualsMethod(method) &&!AopUtils.isHashCodeMethod(method) && !AopUtils.isToStringMethod(method) ?methodProxy : null);}@Override@Nullablepublic Object proceed() throws Throwable {try {return super.proceed();}catch (RuntimeException ex) {throw ex;}catch (Exception ex) {if (ReflectionUtils.declaresException(getMethod(), ex.getClass())) {throw ex;}else {throw new UndeclaredThrowableException(ex);}}}/*** Gives a marginal performance improvement versus using reflection to* invoke the target when invoking public methods.*/@Overrideprotected Object invokeJoinpoint() throws Throwable {if (this.methodProxy != null) {return this.methodProxy.invoke(this.target, this.arguments);}else {return super.invokeJoinpoint();}}
}

下面的代码更重要,下面的代码就是spring-tx模块声明式事务最重要的流程,了解该流程,彻底了解spring-tx,我在示例当中使用的是西卡里(Hikari)数据源,使用其他数据源也是可以的

import java.lang.reflect.Method;
import java.util.ArrayList;
import javax.sql.DataSource;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.AnnotationTransactionAttributeSource;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionInterceptor;
import com.zaxxer.hikari.HikariDataSource;public class TransactionInterceptorTestMain {public static DataSource dataSource;static {HikariDataSource ds = new HikariDataSource();// 设置数据库名称,不要忘记修改这个地方ds.setJdbcUrl("jdbc:mysql://localhost:3306/swttest?serverTimezone=UTC&&useSSL=false");ds.setUsername("root");ds.setPassword("123456");dataSource = ds;}// 能看到这个文章的对这个注解肯定熟悉,别忘了加上就行@Transactional(rollbackFor = Exception.class)public void create() {JdbcTemplate jdbc = new JdbcTemplate();jdbc.setDataSource(dataSource);// 执行sql语句,我在数据库中的表名叫t1,里面只有两个字段jdbc.update("insert into t1 values ('1','上班好困')");// 如果下面的注释打开,则因为@Transactional的存在,导致事务回滚// 如果下面的注释打开,则因为@Transactional的存在,导致事务回滚// 如果下面的注释打开,则因为@Transactional的存在,导致事务回滚// throw new RuntimeException("MYS");}public static void main(String[] args) throws Throwable {TransactionInterceptor ti = new TransactionInterceptor();ti.setTransactionManager(new DataSourceTransactionManager(dataSource));ti.setTransactionAttributeSource(new AnnotationTransactionAttributeSource());TransactionInterceptorTestMain obj = new TransactionInterceptorTestMain();Method createMethod = TransactionInterceptorTestMain.class.getMethod("create");MethodInvocation mi = new MysCglibMethodInvocation(null, obj, createMethod, null, null, new ArrayList<>(),null);ti.invoke(mi);}
}

上面的代码就是spring-tx模块声明式事务的核心流程(了解了这个之后,编程式事务轻而易举就能了解),从这个代码中可以清晰的看到几大步骤
1.创建TransactionInterceptor
2.设置TransactionManager
3.设置TransactionAttributeSource
4.执行要执行的方法,本文中就是TransactionInterceptorTestMain.create方法

步骤2和3在相应的链接中我已经阐述过,本文着重分析步骤4

下面是TransactionAspectSupport.invokeWithinTransaction方法的代码片段

// 创建事务
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
Object retVal = null;
try {//执行我们的方法,本文中的create方法用来插入数据retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {// 如果create方法出异常则代码到这里,并执行回滚completeTransactionAfterThrowing(txInfo, ex);throw ex;
}
finally {// 清空当前线程变量里的事务信息cleanupTransactionInfo(txInfo);
}
// 提交事务
commitTransactionAfterReturning(txInfo);

一:createTransactionIfNecessary
该方法主要使用了DataSourceTransactionManager对象的相关方法开启一个事务,其本质上使用了JDBC的Connection.setAutoCommit,最终返回TransactionInfo,所以我将创建事务的细节都挪到此处讲解,以便于更好理解DataSourceTransactionManager类,理解了这个类,就知道spring是开启一个事务的了

TODO 文章尚未完成,2021年1月18日 09:22:08

Spring-tx-TransactionInterceptor类相关推荐

  1. Spring TX源码分析

    一.先思考一下 什么是事务? 事务是一系列数据库操作的集合,在一个事务里,所有有关的数据库操作一起提交或一起回滚 事务用在什么地方? 如果多个数据库操作需要一起生效或一起失效,那么这些操作需要放在一个 ...

  2. 聊聊spring tx的EnableTransactionManagement

    序 本文主要研究一下spring tx的EnableTransactionManagement EnableTransactionManagement spring-tx-5.1.6.RELEASE- ...

  3. Spring学习-Spring Tx

    一.概述 Spring Tx 全称为 Spring Transaction Management(Spring 事务管理),是 Spring 为 DB 事务管理提供过的一种便捷的接入方式. 二.导入依 ...

  4. 17、Spring Boot普通类调用bean【从零开始学Spring Boot】

    转载:http://blog.csdn.net/linxingliang/article/details/52013017 我们知道如果我们要在一个类使用spring提供的bean对象,我们需要把这个 ...

  5. Spring JDBC-NamedParameterJdbcTemplate模板类

    概述 示例 BeanPropertySqlParameterSource 使用示例 MapSqlParameterSource使用示例 NamedParameterJdbcTemplate 支持 in ...

  6. 四 Spring的工厂类,xml的配置

    Spring工厂类的结构图: BeanFactory:老版本的工厂类 BeanFactory:调用getBean的时候,才会生产类的实例 ApplicationFactory:新版本的工厂类 加载配置 ...

  7. spring tx:advice 和 aop:config 配置事务

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u010741376/article/details/46584463 spring tx:advic ...

  8. spring MVC请求处理类注解属性详解

    spring MVC请求处理类注解属性详解

  9. Spring MVC普通类或工具类中调用service报空空指针的解决办法(调用service报java.lang.NullPointerException)...

    当我们在非Controller类中应用service的方法是会报空指针,如图: 这是因为Spring MVC普通类或工具类中调用service报空null的解决办法(调用service报java.la ...

  10. spring管理的类如何调用非spring管理的类

    spring管理的类如何调用非spring管理的类. 就是使用一个spring提供的感知概念,在容器启动的时候,注入上下文即可. 下面是一个工具类. 1 import org.springframew ...

最新文章

  1. php字符串替换多余逗号_PHP字符过滤函数去除字符串最后一个逗号(rtrim)
  2. MYSQL备份与恢复精华篇
  3. ACM/ICPC2014鞍山现场赛E hdu5074Hatsune Miku
  4. JS 之 数据类型转换
  5. 【算法基础】坚持刷题678天的感受!
  6. 【NLP傻瓜式教程】手把手带你HAN文本分类(附代码)
  7. 案例十:输入一批整数,输出其中的最大值和最小值,输入数字0时结束循环。...
  8. python测试需要学什么_从手工测试到自动化测试需要学什么?
  9. 【Alljoyn】Alljoyn学习笔记五 AllJoyn开源技术基础概念解析
  10. orbeon form 通过 url 的方式同第三方应用集成的开发明细
  11. VS扩展CodeMaid代码整理插件
  12. .NET Core + Ocelot:API 网关
  13. 谈谈一些有趣的CSS题目(十五)-- 谈谈 CSS 关键字 initial、inherit 和 unset
  14. 禁止迅雷:迅雷服务器地址大全+ISA计算机集(xml)
  15. Python学习(三十七)—— 模板语言之自定义filter和中间件
  16. 大脚导入配置选择哪个文件_「干货」图解 IntelliJ IDEA 最常用配置,适合新手
  17. 翻译:如何理解K-means的缺点
  18. 计算机局域网共享本地安全策略,如何设置局域网共享
  19. xp我的计算机不在桌面怎么办,xp系统开机后不显示桌面怎么办|xp电脑开机不显示桌面解决方法...
  20. hp proliant dl380从U盘启动按哪个键

热门文章

  1. Problem Statement
  2. Servlet向JSP传递数据以及JSP页面DIV定时局部刷新
  3. win7下ado连接mysql_提示连接无法用于执行此操作_ADODB.Recordset (0x800A0E7D)连接无法用于执行此操作。在此上下文中它可能已被关闭或无效。...
  4. python采集代理ip_Python采集代理ip并判断是否可用和定时更新的方法
  5. Calendar导入java,Java程序使用Calendar.add()方法将分钟添加到当前时间
  6. mysql的实践小结的作文_MySql小结
  7. pythonweb快速开发平台_30分钟快速搭建Web CRUD的管理平台--django神奇魔法
  8. mysql查询删除重复数据
  9. 在UAP中如何通过WebView控件进行C#与JS的交互
  10. php里面用魔术方法和匿名函数闭包函数动态的给类里面添加方法