- 基本原理
- Spring的事务,本质上是依赖于数据库的事务
- 事务,具体指有限操作的集合。集合具有数据一致和操作隔离的特性
- 声明式事务
- 配置DataSource
- 配置事务管理器
- 事务的传播特性
- Spring中使用注解@Transactional来声明事务,添加该注解的类和方法,提供事务支持。
- 子主题
- 属性-ACID
- A-原子性(Atomicity)
- 事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行。
- C-一致性(Consistency)
- 事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态的含义是数据库中的数据应满足完整性约束。
- I-隔离性(Isolation)
- 多个事务并发执行时,一个事务的执行不应影响其他事务的执行。
- D-持久性(Durability)
- 已被提交的事务对数据库的修改应该永久保存在数据库中。
- 刚性事务
- 严格遵循ACID属性的事务
- 柔性事务
- 期望最终一致性,在事务执行的中间状态允许暂时不遵循ACID属性的事务
- A-原子性(Atomicity)
- 隔离级别
- 传播属性,就是定义在存在多个事务同时存在的时候,spring应该如何处理这些事务的行为。这些属性在TransactionDefinition中定义
- 数据库
- 读未提交(READ UNCOMMITTED)
- 脏读
- 另一个事务修改了数据,但尚未提交,而本事务中的SELECT会读到这些未被提交的数据。
- 脏读
- 读已提交(READ COMMITTED)
- 不重复读
- 同一个事务执行过程中,另外一个事务提交了新数据,因此本事务先后两次读到的数据结果会不一致。
- 不重复读
- 可重复读(REPEATABLE READ)
- 幻读
- 如果另一个事务同时提交了新数据,本事务再更新时,就会“惊奇的”发现了这些新数据
- 幻读
- 串行化(SERIALIZABLE)
- 读操作会隐式获取共享锁,可以保证不同事务间的互斥
- InnoDB默认的隔离级别是REPEATABLE READ
- 读未提交(READ UNCOMMITTED)
- Spring
- ISOLATION_DEFAULT
- 这是个 PlatfromTransactionManager 默认的隔离级别,使用数据库默认的事务隔离级别。另外四个与 JDBC 的隔离级别相对应。
- ISOLATION_READ_UNCOMMITTED
- ISOLATION_READ_COMMITTED
- ISOLATION_REPEATABLE_READ
- ISOLATION_SERIALIZABLE
- ISOLATION_DEFAULT
- 数据库
- 传播机制
- PROPAGATION_REQUIRED
- 表示当前方法必须在一个具有事务的上下文中运行,如有客户端有事务在进行,那么被调用端将在该事务中运行,否则的话重新开启一个事务。(如果被调用端发生异常,那么调用端和被调用端事务都将回滚)
- PROPAGATION_SUPPORTS
- 表示当前方法不必需要具有一个事务上下文,但是如果有一个事务的话,它也可以在这个事务中运行
- PROPAGATION_MANDATORY
- 表示当前方法必须在一个事务中运行,如果没有事务,将抛出异常
- PROPAGATION_NESTED
- 表示如果当前方法正有一个事务在运行中,则该方法应该运行在一个嵌套事务中,被嵌套的事务可以独立于被封装的事务中进行提交或者回滚。如果封装事务存在,并且外层事务抛出异常回滚,那么内层事务必须回滚,反之,内层事务并不影响外层事务。如果封装事务不存在,则同PROPAGATION_REQUIRED的一样
- PROPAGATION_NEVER
- 表示当方法务不应该在一个事务中运行,如果存在一个事务,则抛出异常
- PROPAGATION_REQUIRES_NEW
- 表示当前方法必须运行在它自己的事务中。一个新的事务将启动,而且如果有一个现有的事务在运行的话,则这个方法将在运行期被挂起,直到新的事务提交或者回滚才恢复执行。
- PROPAGATION_NOT_SUPPORTED
- 表示该方法不应该在一个事务中运行。如果有一个事务正在运行,他将在运行期被挂起,直到这个事务提交或者回滚才恢复执行
- PROPAGATION_REQUIRED
- AOP增强
- jdk代理
- 代理接口,不拦截私有方法-接口内不可定义
- Java动态代理
- 步骤
- 1、创建调用处理器,通过实现InvocationHandler接口完成
- 2、创建动态代理类,通过为Proxy类指定ClassLoader对象和一组interface来完成
- 3、使用反射技术获得动态代理类的构造方法
- 4、创建动态代理类实例,使用构造方法创建,调用处理器对象作为参数被传入
- cglib代理
- 也不会拦截私有方法
- CGLIB代理(Code Generation Library)是一个强大的代码生成类库。它能够在运行期扩展Java类与实现Java接口
- cglib封装了asm,可以在运行期动态生成新的class(子类)
- cglib用于AOP,jdk中的proxy必须基于接口,cglib却没有这个限制。
- 原理区别
- java动态代理实质是生成了一个实现了代理接口的匿名类,这个过程使用的是反射技术来完成的,在调用具体方法前调用InvokeHandler来处理。
- cglib动态代理是对代理对象类的class文件加载进来,修改其字节码生成子类来处理,这个过程是通过asm开源包来实现的
- 使用说明
- 默认情况下,实现了接口的目标对象会采用JDK的动态代理实现AOP
- 也可以强制使用CGLIB实现AOP
- 目标对象没有实现接口,必须采用CGLIB库,Spring会自动在JDK动态代理和CGLIB之间转换
- Spring对方法的增强方式
- 前置增强(org.springframework.aop.BeforeAdvice)
- 在目标方法执行之前进行增强
- 后置增强(org.springframework.aop.AfterReturningAdvice)
- 在目标方法执行之后进行增强;
- 环绕增强(org.aopalliance.intercept.MethodInterceptor)
- 在目标方法执行前后都执行增强;
- 异常抛出增强(org.springframework.aop.ThrowsAdvice)
- 在目标方法抛出异常后执行增强;
- 引介增强(org.springframework.aop.IntroductionInterceptor)
- 为目标类添加新的方法和属性。
- 前置增强(org.springframework.aop.BeforeAdvice)
- jdk代理
- 事务抽象
- 接口PlatformTransactionManager定义了事务操作的行为,其依赖TransactionDefinition和TransactionStatus接口,其实大部分的事务属性和行为我们以MySQL数据库为例已经有过了解,这里再对应介绍下。
- PlatformTransactionManager
- 事务管理器
- getTransaction方法
- 事务获取操作,根据事务属性定义,获取当前事务或者创建新事物;
- commit方法
- 事务提交操作,注意这里所说的提交并非直接提交事务,而是根据当前事务状态执行提交或者回滚操作;
- rollback方法
- 事务回滚操作,同样,也并非一定直接回滚事务,也有可能只是标记事务为只读,等待其他调用方执行回滚。
- TransactionDefinition
- 事务属性定义
- getPropagationBehavior方法
- 返回事务的传播属性,默认是PROPAGATION_REQUIRED;
- getIsolationLevel方法
- 返回事务隔离级别,事务隔离级别只有在创建新事务时才有效,也就是说只对应传播属性PROPAGATION_REQUIRED和PROPAGATION_REQUIRES_NEW;
- getTimeout方法
- 返回事务超时时间,以秒为单位,同样只有在创建新事务时才有效
- isReadOnly方法
- 是否优化为只读事务,支持这项属性的事务管理器会将事务标记为只读,只读事务不允许有写操作,不支持只读属性的事务管理器需要忽略这项设置,这一点跟其他事务属性定义不同,针对其他不支持的属性设置,事务管理器应该抛出异常。
- getName方法
- 返回事务名称,声明式事务中默认值为“类的完全限定名.方法名”
- TransactionStatus
- 当前事务状态
- isNewTransaction
- 当前方法是否创建了新事务(区别于使用现有事务以及没有事务)
- hasSavepoint
- 在嵌套事务场景中,判断当前事务是否包含保存点;
- setRollbackOnly和isRollbackOnly
- 只读属性设置(主要用于标记事务,等待回滚)和查询;
- flush
- 刷新底层会话中的修改到数据库,一般用于刷新如Hibernate/JPA的会话,是否生效由具体事务资源实现决定;
- isCompleted
- 判断当前事务是否已完成(已提交或者已回滚)
- PlatformTransactionManager
- 接口PlatformTransactionManager定义了事务操作的行为,其依赖TransactionDefinition和TransactionStatus接口,其实大部分的事务属性和行为我们以MySQL数据库为例已经有过了解,这里再对应介绍下。