Spring 事务笔记
代码写着写着就钻进源码了。
概念
InfrastructureProxy 结构代理
百度查了查,这个类还没有解释。
进去看了一下:
Interface to be implemented by transparent resource proxies that need to be considered as equal to the underlying resource, for example for consistent lookup key comparisons.
Note that this interface does imply such special semantics and does not constitute a general-purpose mixin!Such wrappers will automatically be unwrapped for key comparisons in TransactionSynchronizationManager.
Only fully transparent proxies, e.g. for redirection or service lookups, are supposed to implement this interface. Proxies that decorate the target object with new behavior, such as AOP proxies, do not qualify here!
中文翻译如下:
透明资源代理要实现的接口,为了被认为等同于底层资源,例如用于一致的查找的关键字比较。
注意,这个接口意味着这样的特殊语义,并不构成一般用途的聚合!
这种包装器将在TransactionSynchronizationManager中自动被拆箱来进行关键字比较。
只有完全透明的代理,例如 对于重定向或服务查找,应该实现此接口。 使用新行为来装饰目标对象的代理(例如AOP代理)不适用于此处!
也就是相当于对象本身等同于所封装的内部对象。
代码:
static Object unwrapResourceIfNecessary(Object resource) {
Assert.notNull(resource, "Resource must not be null");
Object resourceRef = resource;
// unwrap infrastructure proxy
if (resourceRef instanceof InfrastructureProxy) {
resourceRef = ((InfrastructureProxy) resourceRef).getWrappedObject();
}
if (aopAvailable) {
// now unwrap scoped proxy
resourceRef = ScopedProxyUnwrapper.unwrapIfNecessary(resourceRef);
}
return resourceRef;
}
这个方法在TransactionSynchronizationUtils中。
再看看调用者:TransactionSynchronizationManager
public static Object getResource(Object key) {
Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
Object value = doGetResource(actualKey);
if (value != null && logger.isTraceEnabled()) {
logger.trace("Retrieved value [" + value + "] for key [" + actualKey + "] bound to thread [" +
Thread.currentThread().getName() + "]");
}
return value;
}
private static Object doGetResource(Object actualKey) {
Map<Object, Object> map = resources.get();
if (map == null) {
return null;
}
Object value = map.get(actualKey);
// Transparently remove ResourceHolder that was marked as void...
if (value instanceof ResourceHolder && ((ResourceHolder) value).isVoid()) {
map.remove(actualKey);
// Remove entire ThreadLocal if empty...
if (map.isEmpty()) {
resources.remove();
}
value = null;
}
return value;
}
resources 就是 NamedThreadLocal,这个不用多说。
如果里面存放的是ResourceHolder并且是Void标记,就透明地移除掉。
调用者是sqlSessionUtils
import static org.springframework.transaction.support.TransactionSynchronizationManager.getResource;
public static SqlSession getSqlSession(SqlSessionFactory sessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) {
....
SqlSessionHolder holder = (SqlSessionHolder) getResource(sessionFactory);
//如果hold已经存在并且不为空。
if (holder != null && holder.isSynchronizedWithTransaction()) {
if (holder.getExecutorType() != executorType) {
throw new TransientDataAccessResourceException("Cannot change the ExecutorType when there is an existing transaction");
}
//直接返回
return holder.getSqlSession();
}
//打开Session
SqlSession session = sessionFactory.openSession(executorType);
.....
if (isSynchronizationActive()) {
Environment environment = sessionFactory.getConfiguration().getEnvironment();
if (environment.getTransactionFactory() instanceof SpringManagedTransactionFactory) {
holder = new SqlSessionHolder(session, executorType, exceptionTranslator);
bindResource(sessionFactory, holder);//绑定到TransactionSynchronizationManager
registerSynchronization(new SqlSessionSynchronization(holder, sessionFactory));
holder.setSynchronizedWithTransaction(true);//将连接资源标记为已经同步过
holder.requested();
} else {
//如果不是Spring管理的事务,则看看是不是错误得被搞进Spring了。
if (getResource(environment.getDataSource()) == null) {
if (logger.isDebugEnabled()) {
logger.debug("SqlSession [" + session + "] was not registered for synchronization because DataSource is not transactional");
}
} else {
throw new TransientDataAccessResourceException(
"SqlSessionFactory must be using a SpringManagedTransactionFactory in order to use Spring transaction synchronization");
}
}
} else {
//同步没有激活,不需要注册到同步事务中
if (logger.isDebugEnabled()) {
logger.debug("SqlSession [" + session + "] was not registered for synchronization because synchronization is not active");
}
}
return session;
}
Spring 事务笔记的更多相关文章
- spring 事务 笔记3.1
Spring事务 以前的事务都是编程式事务,需要开启和关闭,然后程序写在这里面 spring,声明式事务 Spring事务隔离级别 DEFAULT 使用数据库默认隔离级别 READ_UNCOMMITT ...
- Spring事务笔记
1:在同一个类中,如果A方法有事务,B方法也有事务(propagation = Propagation.REQUIRES_NEW),如下代码所示: @Override@Transactionalpub ...
- Spring 事务管理笔记
本文为 Spring 框架的事务管理学习笔记,官网文档地址为:Transaction Management,隔离级别及传播属性解释来自 org.springframework.transaction. ...
- Java框架spring 学习笔记(十八):事务管理(xml配置文件管理)
在Java框架spring 学习笔记(十八):事务操作中,有一个问题: package cn.service; import cn.dao.OrderDao; public class OrderSe ...
- 本人遇到的spring事务之UnexpectedRollbackException异常解决笔记
本人最近在使用spring事务管理的过程中遇到如下异常,导致服务端抛出500给前端,让搞前端的哥们抱怨我心里着实不爽,前前后后折腾了近半个小时才得于解决,今天就做个笔记,以免日后又犯这个错误.好了,错 ...
- Spring 源码学习笔记11——Spring事务
Spring 源码学习笔记11--Spring事务 Spring事务是基于Spring Aop的扩展 AOP的知识参见<Spring 源码学习笔记10--Spring AOP> 图片参考了 ...
- Spring事务源码阅读笔记
1. 背景 本文主要介绍Spring声明式事务的实现原理及源码.对一些工作中的案例与事务源码中的参数进行总结. 2. 基本概念 2.1 基本名词解释 名词 概念 PlatformTransaction ...
- Spring学习笔记五:Spring进行事务管理
转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6776256.html 事务管理主要负责对持久化方法进行统一的提交或回滚,Spring进行事务管理即我们无需在 ...
- Spring事务管理笔记
事务的目的就是要保证数据的高度完整性和一致性. 在实际的项目中,大多都是使用注解的方式来实现事物,这里也就简单记录下使用@Transactional方法和注意事项. 在xml中添加配置 1234567 ...
随机推荐
- APP自动化测试的环境配置
什么是Appium? 第三方自动化框架(工具),扩充了selenium webdriver 协议,在原有的基础上添加了移动端测试API selenium webdriver 指定了客户端到服务端的协议 ...
- Python学习-迭代器、生成器
一.迭代器 1. 可迭代对象 我们知道字符串.列表.元组.字典.集合都可以使用for语句进行循环遍历,然后输出每一个元素,这些都是可迭代对象. 检查对象是否是可迭代对象可以用两种方式去判断: (1)使 ...
- Webpack配置区分开发环境和生产环境
在项目开发的时候,我们通常会将程序分为开发环境和生产环境(或者叫线上环境),开发环境通常指的是我们正在开发的这个阶段所需要的一些环境配置,也就是方便我们开发人员调试开发的一种环境:生产环境通常指的是我 ...
- 品Spring:SpringBoot发起bean定义注册的“二次攻坚战”
上一篇文章整体非常轻松,因为在容器启动前,只注册了一个bean定义,就是SpringBoot的主类. OK,今天接着从容器的启动入手,找出剩余所有的bean定义的注册过程. 具体细节肯定会颇为复杂,同 ...
- 虚拟机ubuntu 网速慢的解决方法
其实虚拟机网速慢,我觉得就两个限制因素.一个是虚拟机的内存,内存小了,上传和下载的速率就慢了,就像内存小的虚拟机跑得慢是一个道理:还有一个就是网络连接方式,这里我使用的是桥接,之前我使用的NAT模式, ...
- 在Android开发中,当按下home键程序会完全退出时,解决这个BUG:
把这段代码贴到 super.onCreate(savedInstanceState); 之后 //remenber process if(!this.isTaskRoot()) { //判断该Act ...
- Java 学习笔记之 Synchronized锁重入
Synchronized锁重入: 当一个线程得到一个对象锁后,再次请求此对象锁时是可以再次得到该对象的锁.这也证明在一个Synchronized方法/块的内部调用本类的其他Synchronized方法 ...
- Video/audio标签的一些基础使用心得
常用方法 .play():用于音频视频的播放 .pause():用于音频视频的暂停 常用属性 <audio src="Batmobile Battle Mode Reveal Musi ...
- 怎么给slice加一个Insert方法呢?而不用丑陋的两次append….
package main import ( "fmt" "reflect" ) func Insert(slice interface{}, pos int, ...
- Kafka技术原理知识点总结
1.Kafka是由Linkedin公司开发的,使用Scala语言编写的,分布式,多副本,多分区的,发布订阅模式的消息系统,他通常用于日志系统的搭建,2.Kafka和Zookeeper:Kafka通过Z ...