spring tx——@EnableTransactionManagement
@EnableTransactionManagement import了TransactionManagementConfigurationSelector,而TransactionManagementConfigurationSelector继承于AdviceModeImportSelector根据@EnableTransactionManagement配置的AdviceMode引入不同的类。
我们只看proxy模式下引入的AutoProxyRegistrar和ProxyTransactionManagementConfiguration。
AutoProxyRegistrar——引入aop代理
AutoProxyRegistrar继承于ImportBeanDefinitionRegistrar,注册定义用于aop代理生成的InfrastructureAdvisorAutoProxyCreator的BeanDefinition
ProxyTransactionManagementConfiguration——生成事务相关类
- TransactionalEventListenerFactory:其父类AbstractTransactionManagementConfiguration生成一个TransactionalEventListenerFactory用于创建ApplicationListenerMethodTransactionalAdapter,向TransactionSynchronizationManager注册@TransactionalEventListener注解的方法生成的TransactionSynchronization。
- TransactionAttributeSource:用于解析事务注解,包括Spring的@Transactional、jta的@Transactional、ejb3的@TransactionAttribute注解
- TransactionInterceptor:事务通知Advice,完成事务的主要逻辑,底层将获取事务、回滚、提交委托给TransactionManager
- BeanFactoryTransactionAttributeSourceAdvisor:事务切面通知Advisor,通过TransactionAttributeSource判断方法是否包含事务注解,通过TransactionInterceptor完成事务通知。
TransactionInterceptor
TransactionInterceptor主要逻辑位于父类TransactionAspectSupport的invokeWithinTransaction方法
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
final InvocationCallback invocation) throws Throwable {
//1.通过TransactionAttributeSource解析事务注解获取TransactionAttribute,来决定使用何种TransactionManager
TransactionAttributeSource tas = getTransactionAttributeSource();
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
final TransactionManager tm = determineTransactionManager(txAttr);
if (this.reactiveAdapterRegistry != null && tm instanceof ReactiveTransactionManager) {
//tm为ReactiveTransactionManager类型,即响应式的事务管理器逻辑,这里省略。。。
}
PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
//2.创建事务
TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);
//3.执行后续通知和执行代码
Object retVal;
try {
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// 4.抛错异常判断是否回滚
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
// 5.重置线程绑定的TransactionInfo
cleanupTransactionInfo(txInfo);
}
//省略部分无关代码。。。。
//6.提交事务
commitTransactionAfterReturning(txInfo);
return retVal;
}
else {
//tm为CallbackPreferringPlatformTransactionManager类型,即异步回调的事务管理器,使用execute处理事务,这里省略。。。
}
}
1. 根据事务注解决定TransactionManager
protected TransactionManager determineTransactionManager(@Nullable TransactionAttribute txAttr) {
if (txAttr == null || this.beanFactory == null) {
return getTransactionManager();
}
//获取注解配置的TransactionManager,例如@Transactional("dataSourceTransactionManager")
String qualifier = txAttr.getQualifier();
if (StringUtils.hasText(qualifier)) {
return determineQualifiedTransactionManager(this.beanFactory, qualifier);
}
//获取TransactionInterceptor配置的默认transactionManagerBeanName
else if (StringUtils.hasText(this.transactionManagerBeanName)) {
return determineQualifiedTransactionManager(this.beanFactory, this.transactionManagerBeanName);
}
else {
//获取TransactionInterceptor配置的默认transactionManager
TransactionManager defaultTransactionManager = getTransactionManager();
if (defaultTransactionManager == null) {
defaultTransactionManager = this.transactionManagerCache.get(DEFAULT_TRANSACTION_MANAGER_KEY);
if (defaultTransactionManager == null) {
//获取beanFactory中TransactionManager类型的bean
defaultTransactionManager = this.beanFactory.getBean(TransactionManager.class);
this.transactionManagerCache.putIfAbsent(
DEFAULT_TRANSACTION_MANAGER_KEY, defaultTransactionManager);
}
}
return defaultTransactionManager;
}
}
2. 创建事务
protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,
@Nullable TransactionAttribute txAttr, final String joinpointIdentification) {
//省略代码。。。
//通过PlatformTransactionManager开启事务
TransactionStatus status = null;
if (txAttr != null) {
if (tm != null) {
status = tm.getTransaction(txAttr);
}
}
//封装TransactionInfo,并绑定到线程上(即存储在Threadlocal中)
return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
}
3. 执行后续通知和代码
4. 抛错异常判断是否回滚
protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) {
if (txInfo != null && txInfo.getTransactionStatus() != null) {
//1.事务注解上回滚的异常规则与当前异常匹配,执行回滚,即@Transactional(rollbackFor = Exception.class),ex instanceof Exception
if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) {
try {
txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
}
//省略异常处理(日志和抛错)。。。。
catch (TransactionSystemException ex2) {
}
catch (RuntimeException | Error ex2) {
}
}
//1.事务注解上回滚的异常规则与当前异常不匹配,执行提交,但TransactionStatus.isRollbackOnly()为true也会进行回滚
else {
try {
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
}
//省略异常处理(日志和抛错)。。。。
catch (TransactionSystemException ex2) {
}
catch (RuntimeException | Error ex2) {
}
}
}
}
5. 重置线程绑定的TransactionInfo
protected void cleanupTransactionInfo(@Nullable TransactionInfo txInfo) {
//重置为原来的TransactionInfo
if (txInfo != null) {
txInfo.restoreThreadLocalStatus();
}
}
6. 无异常提交事务
protected void commitTransactionAfterReturning(@Nullable TransactionInfo txInfo) {
if (txInfo != null && txInfo.getTransactionStatus() != null) {
if (logger.isTraceEnabled()) {
logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "]");
}
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
}
}
spring tx——@EnableTransactionManagement的更多相关文章
- 学习Spring5必知必会(7)~Spring tx
一.spring的事务管理 1.引出事务的经典例子:银行转账发生异常 ✿ 解决:把转出钱和转入钱的业务放到同一个事务空间. ■ 分析转账过程流程: ① 首先,获取 DataSource 对象: ② 其 ...
- spring tx:advice 和 aop:config 配置事务
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...
- Spring -- <tx:annotation-driven>注解基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)的区别。
借鉴:http://jinnianshilongnian.iteye.com/blog/1508018 基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional ...
- Spring <tx:annotation-driven>注解 JDK动态代理和CGLIB动态代理 区别。
基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别. 我还是喜欢基于Schema风格的Spring事务管理,但也有很多人在用基于@Tras ...
- [转]spring tx:advice 和 aop:config 配置事务
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www. ...
- spring 事务 @EnableTransactionManagement原理
@EnableXXX原理:注解上有个XXXRegistrar,或通过XXXSelector引入XXXRegistrar,XXXRegistrar实现了 ImportBeanDefinitionRegi ...
- spring tx:advice事务配置
http://blog.csdn.net/bao19901210/article/details/17226439 http://blog.csdn.net/rong_wz/article/detai ...
- spring tx——TransactionManger
TransactionDefinition--事务定义 定义事务属性,包括传播级别.隔离级别.名称.超时.只读等 TransactionStatus--事务状态 事务状态,包含事务对象(jdbc为Da ...
- Unable to locate Spring NamespaceHandler for XML schema namespace [http://www.springframework.org/schema/tx]
ERROR - Context initialization failed org.springframework.beans.factory.parsing.BeanDefinitionParsin ...
随机推荐
- python3 闭包函数 装饰器
闭包函数 1.闭:定义在函数内部的函数 2.包:内部函数引用了外部函数作用域的名字 在函数编程中经常用到闭包.闭包是什么,它是怎么产生的及用来解决什么问题呢.给出字面的定义先:闭包是由函数及其相关的引 ...
- 你的 IDEA 是如何配置的?卡不卡?试试这样配置
本文作者在和同事的一次讨论中发现,对 IntelliJ IDEA 内存采用不同的设置方案,会对 IDE 的速度和响应能力产生不同的影响. Don't be a Scrooge and give you ...
- MyBatis学习笔记(2)--缓存
一.什么是缓存 --存在于内存中的临时数据. 为什么使用缓存?--减少和数据库的交互次数,提高执行效率. 适用于缓存的数据: 1.经常查询并且不经常改变的数据. 2.数据的正确与否对最终结果影响较小的 ...
- MySQL 合并查询,以map或对象的形式返回
转载 CSDN博主「小林子林子」 -> https://blog.csdn.net/qq_26106607/article/details/84961254 原始SQL-> 目的-> ...
- python之单元测试及unittest框架的使用
例题取用登录模块:代码如下 def login_check(username,password): ''' 登录校验的函数 :param username:账号 :param password: 密码 ...
- SpringBoot--整合Lettuce redis
首先解释一下Lettuce客户端: Lettuce 和 Jedis 的都是连接Redis Server的客户端程序.Jedis在实现上是直连redis server,多线程环境下非线程安全,除非使用连 ...
- caffe的python接口学习(2)生成solver文件
caffe在训练的时候,需要一些参数设置,我们一般将这些参数设置在一个叫solver.prototxt的文件里面 有一些参数需要计算的,也不是乱设置. 假设我们有50000个训练样本,batch_si ...
- LQR算法如何跟随变化的期望状态
开门见山,通过LQR的能量函数可以看出,LQR算法是将状态量控制到零(关于能量函数请看我的随笔:LQR要点),但实际控制中我们希望状态量能够跟随期望值 下面将会解决如何用LQR算法跟随变化的期望值: ...
- 手把手教你把web应用丢到服务器上(单页应用+ 服务端渲染)
前两篇文章中,我分别介绍了框架的搭建利用vue-cli + vant搭建一个移动端开发模板,并且把项目中axios请求和vuex的用法做了简要的介绍如何在项目里管理好axios请求与vuex.在这两篇 ...
- 简单案例:form表单应用向后端发数据
效果如下图: 先新建一Django项目. 最后在terminal执行python manage.py runserver 8090 运行djago程序 浏览器输入http://127.0.0.1:80 ...