Spring中事务源码初次接触
软件实现事务的三种方式
- 通过xml代码配置声明式事务
- 通过Java代码实现事务 通过DataSourceTransactionManager 实现
- 通过注解 @Transactional
同一个事务管理的代码逻辑中,每次执行sql语句都是基于同一个连接
通过注解实现事务 @Transactional
ORM框架本身可以获取连接但是无法确保获取的同一事务管理的同一连接,所以引入事务同步管理器通过TransactionSynchronizationManager获取连接。其中引入ThreaLocal概念,它是一个线程级别的变量,每个线程都有一个ThredLocal就是每个线程都拥有自己独立的一个变量,竞争条件就被彻底消除了,在并发模式下是绝对安全的变量。
// 最简化的ORM框架 -- 绑定参数,生成SQL、结果映射、pojo对象 @Component // 交给你spring托管 创建对象 注入 public class MyJdbcTemplate { @Autowired TonyTransactionManage tonyTransactionManage; public void execute(String sql) throws SQLException { // 1. 数据库链接 // dataSource.getConnection(); 这个方法连接池提供的,每次获取一个连接池中空闲连接 Connection connection = tonyTransactionManage.getConnection(); // 这个地方不应管每次都是新连接 // 2. 执行SQL语句 Statement statement = connection.createStatement(); statement.execute(sql); } }
/** * 存放有连接 */ @Component public class TonyTransactionManage { @Autowired DataSource dataSource; private ThreadLocal<Connection> connection = new ThreadLocal<>(); // 多个线程共用了同一个连接,导致回滚的时候出现数据错乱 public Connection getConnection() throws SQLException { if (connection.get() == null) { connection.set( dataSource.getConnection()); } return connection.get(); } }
@Autowired MyJdbcTemplate myJdbcTemplate; // 不用框架事务处理机制 自己去做事务处理? // 事务控制不应在ORM框架,而是业务代码层面 public void delete(String userId) throws Exception { // TODO 事务怎么玩? --- 同一个事务管理的代码调用逻辑中,每次执行SQL语句 基于同一个连接 Connection connection = TonyTransactionManage .getConnection(); connection.setAutoCommit(false); try{ // ---------- 业务 -------------- // SQL自动生成、参数直接传对象、查询结果映射pojo connection.commit(); }catch(Exception e){ e.printStackTrace(); connection.rollback(); } // ------------结束-------------- }
不通过Spring注解或xml实现事务 DataSourceTransactionManager
获取连接 DataSourceTransactionManager .getConnection();
@Autowired DataSourceTransactionManager dataSourceTransactionManager; @Autowired TransactionDefinition transactionDefinition; try{ TransactionStatus status = dataSourceTransactionManager.getTransaction(transactionDefinition); // 业务代码 // 提交 dataSourceTransactionManager.commit(status); ]catch(Exception e){ dataSourceTransactionManager.rollback(status) }
关闭连接中的自动提交 connection.setAutoCommint(false);
try{
--------------------------业务代码-------------------------------------
connection.commit();
}catch(Exception e){
e.printStackTrace();
connection.rollback();
}
通过自定义一个Spring注解实现事务
手动写一个切面
// spring提供AOP 支持到方法层级 @Aspect @Component public class TonyTransactionApesct { @Autowired TonyTransactionManage tonyTransactionManage; // 注解标记 -- 有了这个标记spring就能识别到 需要增强 // 实际方法执行 是按照这个AOP程序重新定义的 @Around("@annotation(TonyTransactional)") public Object doTranscation(ProceedingJoinPoint proceedingJoinPoint) throws SQLException { Connection connection = null; // 原来的业务逻辑- 调用 try { connection = tonyTransactionManage.getConnection(); connection.setAutoCommit(false); // 设置为手动提交 System.out.println("方法执行前 ---- 开启事务"); Object result = proceedingJoinPoint.proceed(); System.out.println("方法执行后 ----提交"); connection.commit(); return result; } catch (Throwable throwable) { throwable.printStackTrace(); System.out.println("方法执行后 ----回滚"); connection.rollback(); } return null; } }
手写一个注解
/** * 事务注解 */ public @interface TonyTransactional { }
扩展
方法调用–》执行前从数据库连接池中获取连接存放至事务同步管理器TransactionSynchronizationManager,开启事务–》需要进行事务处理的具体方法–》ORM框架(绑定参数生成SQL)–》获取数据库连接执行SQ–》从事务同步管理器TransactionSynchronizationManager中获取数据库连接 --》数据库–》pojo结果映射–》需要进行事务处理的具体方法–》执行后提交或回滚
扩展
了解注解的封装方式 ;注解可以理解为一段标记,谁定义的谁去处理
AOP的编程思想–面向切面编程,简单来讲就是增强功能,动态的新的代码逻辑切入到指定的逻辑或指定的位置上;
AOP增强之前
//业务代码
AOP增强之后
// 前面插入新的逻辑 // 业务代码 // 后面插入新的逻辑
扩展
Spring如何实现AOP原理
通过cglib动态生成指定类的子类,然后子类重写父类的方法(待了解)
- spring-事务源码解析(一)
- Spring源码学习之--事务类型
- 2016.01.04接触spring一年开始读spring源码
- [Spring3.x源码]事务(一)配置事务切面
- mybatis源码分析(8)-----事务(mybatis管理、spring管理)
- Spring源码解析(一) Spring事务控制之Hibernate
- 杨老师课堂之springAOP事务控制源码解析
- Spring提取@Transactional事务注解的源码解析
- Spring声明式事务管理源码解读
- 初次接触spring
- spring源码分析之——spring 事务管理实现方式
- spring事务源码分析结合mybatis源码(三)
- 【spring源码学习】spring的事务管理的源码解析
- Spring中的DataSource 事务源码理解
- Spring事务源码解析
- Spring事务源码分析
- 【笔记】Spring 事务原理分析和源码剖析
- 从源码角度剖析 Spring 如何管理 mybatis 事务的?
- Spring提取@Transactional事务注解的源码解析
- spring事务源码