Spring 数据库连接(Connection)绑定线程(Thread)的实现
最近在看spring事务的时候在想一个问题:spring中的很多bean都是单例的,是非状态的,而数据库连接是一种有状态的对象,所以spring一定在创建出connection之后在threadlocal中保存了它。今天正好有空,就看了一下源码:
/**
* Bind the given resource for the given key to the current thread.
* @param key the key to bind the value to (usually the resource factory)
* @param value the value to bind (usually the active resource object)
* @throws IllegalStateException if there is already a value bound to the thread
* @see ResourceTransactionManager#getResourceFactory()
*/
public static void bindResource(Object key, Object value) throws IllegalStateException {
Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
Assert.notNull(value, "Value must not be null");
Map<Object, Object> map = resources.get();
// set ThreadLocal Map if none found
if (map == null) {
map = new HashMap<>();
resources.set(map);
}
Object oldValue = map.put(actualKey, value);
// Transparently suppress a ResourceHolder that was marked as void...
if (oldValue instanceof ResourceHolder && ((ResourceHolder) oldValue).isVoid()) {
oldValue = null;
}
if (oldValue != null) {
throw new IllegalStateException("Already value [" + oldValue + "] for key [" +
actualKey + "] bound to thread [" + Thread.currentThread().getName() + "]");
}
if (logger.isTraceEnabled()) {
logger.trace("Bound value [" + value + "] for key [" + actualKey + "] to thread [" +
Thread.currentThread().getName() + "]");
}
}
代码很简单,以dataSource为key,ConnectionHolder为value存进了一个map里,而这个叫做resources的map是一个Threadlocal变量,存在于当前线程的ThreadlocalMap里。
bindResource是在DataSourceTransactionManager.doBegin()方法中被调用的,来看看这个方法
/**
* This implementation sets the isolation level but ignores the timeout.
*/
@Override
protected void doBegin(Object transaction, TransactionDefinition definition) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
Connection con = null; try {
if (!txObject.hasConnectionHolder() ||
txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
Connection newCon = obtainDataSource().getConnection();
if (logger.isDebugEnabled()) {
logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
}
txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
} txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
con = txObject.getConnectionHolder().getConnection();
//这里设置隔离级别
Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
txObject.setPreviousIsolationLevel(previousIsolationLevel); // Switch to manual commit if necessary. This is very expensive in some JDBC drivers,
// so we don't want to do it unnecessarily (for example if we've explicitly
// configured the connection pool to set it already).
//这里设置自动提交由spring控制
if (con.getAutoCommit()) {
txObject.setMustRestoreAutoCommit(true);
if (logger.isDebugEnabled()) {
logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
}
con.setAutoCommit(false);
} prepareTransactionalConnection(con, definition);
//设置该连接现在已经有事务了
txObject.getConnectionHolder().setTransactionActive(true); int timeout = determineTimeout(definition);
if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
}
// Bind the connection holder to the thread.
//这里把新连接绑定到当前线程
if (txObject.isNewConnectionHolder()) {
TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());
}
} catch (Throwable ex) {
if (txObject.isNewConnectionHolder()) {
DataSourceUtils.releaseConnection(con, obtainDataSource());
txObject.setConnectionHolder(null, false);
}
throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
}
}
该方法的主要作用都写在注释里了,看一下就好。
Spring 数据库连接(Connection)绑定线程(Thread)的实现的更多相关文章
- paip.提升性能----数据库连接池以及线程池以及对象池
paip.提升性能----数据库连接池以及线程池以及对象池 目录:数据库连接池c3po,线程池ExecutorService:Jakartacommons-pool对象池 作者Attilax 艾龙, ...
- Spring单例与线程安全小结
一.Spring单例模式与线程安全 Spring框架里的bean,或者说组件,获取实例的时候都是默认的单例模式,这是在多线程开发的时候要尤其注意的地方. 单例模式的意思就是只有一个实例.单例模式确 ...
- Lua 学习笔记(九)协同程序(线程thread)
协同程序与线程thread差不多,也就是一条执行序列,拥有自己独立的栈.局部变量和命令指针,同时又与其他协同程序共享全局变量和其他大部分东西.从概念上讲线程与协同程序的主要区别在于,一个具有多个线程的 ...
- java 线程 Thread 使用介绍,包含wait(),notifyAll() 等函数使用介绍
(原创,转载请说明出处!谢谢--http://www.cnblogs.com/linguanh/) 此文目的为了帮助大家较全面.通俗地了解线程 Thread 相关基础知识! 目录: --线程的创建: ...
- Spring并发访问的线程安全性问题
Spring并发访问的线程安全性问题 http://windows9834.blog.163.com/blog/static/27345004201391045539953/ 由于Spring MVC ...
- Android 线程Thread的2种实现方法
在讲解之前有以下三点要说明: 1.在Android中有两种实现线程Thread的方法: ①扩展java.long.Thread类: ②实现Runnable()接口: 2.Thread类是线程类,它有两 ...
- 线程(thread)
线程(thread): 现代操作系统引入进程概念,为了并发(行)任务 1.进程之间的这种切换代价很高 2.通信方式的代价也很大基本概念: 1.线程是比进程更小的资源单位,它是进程中的一个执行路线(分支 ...
- Java线程Thread的状态解析以及状态转换分析 多线程中篇(七)
线程与操作系统中线程(进程)的概念同根同源,尽管千差万别. 操作系统中有状态以及状态的切换,Java线程中照样也有. State 在Thread类中有内部类 枚举State,用于抽象描述Java线程的 ...
- Asp.Net任务Task和线程Thread
Task是.NET4.0加入的,跟线程池ThreadPool的功能类似,用Task开启新任务时,会从线程池中调用线程,而Thread每次实例化都会创建一个新的线程.任务(Task)是架构在线程之上的, ...
- 线程 Thread Runnable 守护线程 join MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
随机推荐
- JQuery编写简易京东购物车功能
前天无意间看到有一位程序员的博客,有一篇名为无聊时编写的购物车,看了之后,只是觉得很垃圾,因为代码很臃肿,当然我写的也不咋地,当然我也是复 习一下所学的js,再敲这个的期间遇到了如下问题,1:子元素父 ...
- chrome调试工具高级不完整使用指南(优化篇)
上一篇文章我们说了chrome调试工具的一些比较基础功能的用法,接下来我们要在这一篇文章中说一说,其他一些chrome调试工具的使用方法 2.1.5 Network模块 在netWork模块中,大致上 ...
- SuperSocket入门(四)-命令行协议
前面已经了解了supersocket的一些基本的属性及相关的方法,下面就进入重点的学习内容,通信协议.在没有看官方的文档之前,对于协议的理解首先想到的是TCP和UDP协议.TCP 和 UDP ...
- Python进阶内容(五)--- type和object的关系
面向对象编程(OOP)的两大关系 继承与实现 继承关系: 子类继承自父类(base),可以使用父类的一些方法(method)和属性(attribute) 实现关系: 以类为模板,实例化一个对象,即:对 ...
- 3、ABPZero系列教程之拼多多卖家工具 项目修改及优化
本篇内容杂而简单,不需要多租户.不需要多语言.使用MPA(多页面).页面加载速度提升…… 刚登录系统会看到如下界面,这不是最终想要的效果,以下就一一来修改. 不需要多租户 AbpZeroTemplat ...
- (GO_GTD_2)基于OpenCV和QT,建立Android图像处理程序
一.综述 如何采集图片?在windows环境下,我们可以使用dshow,在linux下,也有ffmpeg等基础类库,再不济,opencv自带的videocapture也是提供了基础的支撑.那么 ...
- 微信小程序——Now you can provide attr "wx:key" for a "wx:for" to improve performance.
在官方的swiper(滑块视图容器)中demo代码,运行时会出现Now you can provide attr "wx:key" for a "wx:for" ...
- app额外后台运行操作
//在视图中运行操作中进行周期操作 - (void)applicationDidEnterBackground:(UIApplication *)application { [self beingBa ...
- 明星单品tab
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- Mac搭建cocos2dx+Android studio开发环境以及AnySDK的集成
配置环境: mac osx 10.12.6 cocos2dx 3.14 Android studio 2.3 目标: 在mac上配置cocos Android开发环境,接入AnySDK 配置: 1.安 ...