一、概述
Spring-tx的事务处理是基于Spring-aop包的机制,我们平时使用@Transactional来为方法包裹事务的所有解析和实现过程,都是通过面向切面来实现的。
实现一个AOP机制,需要切面执行器Advisor,切面PointCut,切面逻辑Advice三个接口来完成。
在Transaction的解析和包裹切面逻辑的过程中,这三个接口实现类分别为:
Advisor:BeanfactoryTransactionAttributeSourceAdvisor
PointCut:TransactionAttributeSource
Advice:TransactionInterceptor
二、TransactionInterceptor的逻辑过程:
1.通过实现BeanfactoryAware获取BeanFactory
2.获取切面上的@Transactional中的所有属性,并将不为空的TransactionManager缓存其与切面方法的映射关系,方便之后直接调用
3.获取@Trasactional的过程中用的是面向组合的思想,TransactionInterceptor通过TransactionAttributeSource来获取所需的属性,而TransactionAttributeSource只负责缓存,它会去调用TransactionAnnotationParser来解析外面传给它的Method方法,最终TransactionAnnotationParser会调用工具类AnnotatedElementUtils读取方法的@Transactional注解的所有属性解析成AnnotationAttributes,然后再进行定制化解析,返回TransactionAttribute。
另外TransactionAttributeSource再缓存映射关系时用了元数据的思想,对于我们默认的@Transactional()注解,它对应的TransactionAttribute对象是TransactionAttributeSource再初始化时候就提前生成的一个对象,这样可以节约存储空间。
4.使用TransactionManager.getTransaction来尝试建立一个事务并获取事务信息对象TransactionInfo,若当前线程已经有事务TransactionInfo,则把之前的TransactionInfo保存在新建立的TransactionInfo对象里,然后把TransactionManager对象的ThreadLocal里保存的TransactionInfo更新为新建立的对象。
至于事务到底是begin还是suspend还是抛出异常,都由TransactionManager决定,具体逻辑可以自行搜索Propagation并对照TransactionManager.getTransaction方法来学习。
5.执行被代理的方法
6.处理异常:不需要回滚的:异常不是@Transactional中的Exception及其子类,不回滚继续提交。
需要回滚的:通过调用事务信息的TransactionManager.rollback对异常进行回滚处理,此处有四种回滚:新建的事务:直接回滚;有savePoint的事务:回滚到上一次的savePoint;有被挂起的事务:恢复挂起事务
7.清除ThreadLocal中的事务信息,更改为上一次的事务信息
8.尝试提交事务,若当前TransactionStatus被设置为rollbackOnly或者isGlobalRollbackOnly成立,就直接回滚事务,否则提交事务
9.返回代理方法执行结果