代码写着写着就钻进源码了。

概念

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 事务笔记的更多相关文章

  1. spring 事务 笔记3.1

    Spring事务 以前的事务都是编程式事务,需要开启和关闭,然后程序写在这里面 spring,声明式事务 Spring事务隔离级别 DEFAULT 使用数据库默认隔离级别 READ_UNCOMMITT ...

  2. Spring事务笔记

    1:在同一个类中,如果A方法有事务,B方法也有事务(propagation = Propagation.REQUIRES_NEW),如下代码所示: @Override@Transactionalpub ...

  3. Spring 事务管理笔记

    本文为 Spring 框架的事务管理学习笔记,官网文档地址为:Transaction Management,隔离级别及传播属性解释来自 org.springframework.transaction. ...

  4. Java框架spring 学习笔记(十八):事务管理(xml配置文件管理)

    在Java框架spring 学习笔记(十八):事务操作中,有一个问题: package cn.service; import cn.dao.OrderDao; public class OrderSe ...

  5. 本人遇到的spring事务之UnexpectedRollbackException异常解决笔记

    本人最近在使用spring事务管理的过程中遇到如下异常,导致服务端抛出500给前端,让搞前端的哥们抱怨我心里着实不爽,前前后后折腾了近半个小时才得于解决,今天就做个笔记,以免日后又犯这个错误.好了,错 ...

  6. Spring 源码学习笔记11——Spring事务

    Spring 源码学习笔记11--Spring事务 Spring事务是基于Spring Aop的扩展 AOP的知识参见<Spring 源码学习笔记10--Spring AOP> 图片参考了 ...

  7. Spring事务源码阅读笔记

    1. 背景 本文主要介绍Spring声明式事务的实现原理及源码.对一些工作中的案例与事务源码中的参数进行总结. 2. 基本概念 2.1 基本名词解释 名词 概念 PlatformTransaction ...

  8. Spring学习笔记五:Spring进行事务管理

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6776256.html  事务管理主要负责对持久化方法进行统一的提交或回滚,Spring进行事务管理即我们无需在 ...

  9. Spring事务管理笔记

    事务的目的就是要保证数据的高度完整性和一致性. 在实际的项目中,大多都是使用注解的方式来实现事物,这里也就简单记录下使用@Transactional方法和注意事项. 在xml中添加配置 1234567 ...

随机推荐

  1. 云原生生态周报 Vol. 21 | Traefik 2.0 正式发布

    作者 | 浔鸣.心水.元毅.源三.衷源 业界要闻 CNCF 计划将 TOC 升至 11 人 技术监督委员会(TOC)是 CNCF 的三大核心管理机构之一,从 2020 年 1 月起,TOC 将从 9 ...

  2. 常用HBase操作

    HBase是一个分布式.面向列的数据库,可以用来存储非结构化和半结构化的松散数据,具有高可靠.高性能.面向列.可伸缩的特性.通过行键(RowKey).列族(ColumnFamily).列(Column ...

  3. WPS删除多余空白页

    WPS删除多余空白页 在实际工作中,我们在操作WPS文字的时候常常会遇到一种问题,就是当在文字占满整页的时候,文档常常会多出一页空白页的现象.如图1 图 1   对于WPS文字怎么删除空白页这个问题, ...

  4. JVM 调优 - jhat

    Java命令学习系列(五)——jhat 2016-01-21 分类:Java 阅读(8708) 评论(3) 阿里大牛珍藏架构资料,点击链接免费获取 jhat(Java Heap Analysis To ...

  5. API离线查看工具【包括!!所用常用!!开发语言的API】

    我相信对于每一个开发人员来说,都是不喜欢死记硬背API的,一些常用的方法或者接口我们是可以直接信手捏来的,或者说直接使用开发工具的自动代码提示,也能很快的找到自己想用的API,如果是自己从未使用过的, ...

  6. Flask基础(17)-->防止 CSRF 攻击

    CSRF CSRF全拼为Cross Site Request Forgery,译为跨站请求伪造. CSRF指攻击者盗用了你的身份,以你的名义发送恶意请求. 包括:以你名义发送邮件,发消息,盗取你的账号 ...

  7. 【ASP.NET基础--MVC】MVC视图基础语法学习

    初步接触.net MVC的视图语法,很多东西都不太熟悉,感觉跟之前的aspx以及html都有一些区别,最近看别人的代码,一边看一边研究,现把学到的东西在这里记录一下,以便日后翻阅. 第一部分:基础知识 ...

  8. MongoDB 学习笔记之 索引选项和重建索引

    索引选项: {background:true}在后台创建索引,索引在构建过程中,其他客户端仍然可以查询数据,不会阻塞. db.comments.createIndex({anonymous: 1},{ ...

  9. Spring Boot 2.X(二):集成 MyBatis 数据层开发

    MyBatis 简介 概述 MyBatis 是一款优秀的持久层框架,支持定制化 SQL.存储过程以及高级映射.它采用面向对象编程的方式对数据库进行 CRUD 的操作,使程序中对关系数据库的操作更方便简 ...

  10. win10家庭版升级专业版

    在网上随便百度一个产品密钥,记得一定要先断网(这个很重要),否则很难升级. 升级之后发现产品未激活,下载KMS激活一下就可以了.