美文网首页spring框架SSHkjjava
透彻理解Spring事务设计思想之手写实现

透彻理解Spring事务设计思想之手写实现

作者: 张丰哲 | 来源:发表于2017-08-01 22:15 被阅读2340次

前言

事务,是描述一组操作的抽象,比如对数据库的一组操作,要么全部成功,要么全部失败。事务具有4个特性:Atomicity(原子性),Consistency(一致性),Isolation(隔离性),Durability(持久性)。在实际开发中,我们对事务应用最多就是在数据库操作这一环,特别是Spring对数据库事务进行了封装管理。Spring对事务的支持,确实很强大,但是从本质上来讲:事务是否生效取决数据库底层是否支持(比如MySQL的MyISAM引擎就不支持事务,Spring能奈何!),同时一个事务的多个操作需要在同一个Connection上。事务也往往是在业务逻辑层来控制。本篇博客将通过手写一个Demo来分析Spring事务底层到底是如何帮助我们轻松完成事务管理的!

透彻理解Spring事务设计思想之手写实现

先来看一眼工程结构:

工程结构

ConnectionHolder

ConnectionHolder

在Spring中,有时候我们是不是要配置多个数据源DataSource?很显然,Spring需要通过DataSource来得到操作数据库的管道Connection,这有点类似于JNDI查找。

这里通过ConnectionHolder类来完成这个过程,需要思考的是在多线程下,这显然是存在问题的。为避免多线程问题,难道我们采用线程安全的Map,比如ConcurrentHashMap,其实我们真正的目的是什么?是保证一个线程下,一个事务的多个操作拿到的是一个Connection,显然使用ConcurrentHashMap根本无法保证!

Spring很聪明,她提供了一种思路,来解决,看下面的代码!

SingleThreadConnectionHolder

SingleThreadConnectionHolder

本来线程不安全的,通过ThreadLocal这么封装一下,立刻就变成了线程的局部变量,不仅仅安全了,还保证了一个线程下面的操作拿到的Connection是同一个对象!这种思想,确实非常巧妙,这也是无锁编程思想的一种方式!

TransactionManager

TransactionManager

TransactionManager,这个我们经常在Spring里面进行配置吧,事务大管家!

UserAccountDao、UserOrderDao

UserAccountDao UserOrderDao

这里通过这2个DAO,想模拟一个事务中账户购买、下单2个操作。

UserService

UserService

到这里,可以清晰的看到Spring事务管理的一个缩影了吧!

Test

测试

这里,主要是模拟Spring的注入以及多用户并发请求。

运行结果

运行结果

你可以发现,一个线程中的一个事务的多个操作,使用的是同一个Connection!

好了,到这里,你是否能对Spring实现事务的思想有所了解呢?

晚安,早点睡觉,明天继续,O(∩_∩)O哈哈~

相关文章

网友评论

  • f7cb34fabb0d:我想问下,如果这个业务执行到一半,系统发生了垃圾回收,将当前的ThreadLocalMap中的key回收了,也就是ThreadLocal这个对象被回收,这时即使value还存在,但是由于key为null,当再次调用ThreadLocal.get()方法也是找不到当前的value,对应你文章中的就是找不到connection,那这时候就会生成一个新的connection,这样俩个service获得的connection就不是同一个,你觉得会出现我说的这种情况吗,如果出现了怎么解决呢?
  • Disker:大牛,请问源码在哪里可以观摩呀?
    张丰哲:下次我改进下,代码都提供下载哈。本文代码先凑合着看看图片吧:smiley:
  • a072fa038320:很感谢 写出这么通俗易懂的文章!!! 有一个疑问,一个Connection的过程中,是可以有多个事务的吗? 比如SprinG的事务传播特性中,nested, require_new 等 都是要新建一个事务,进行处理。这样理解对吗?
    张丰哲:PROPAGATION_REQUIRES_NEW 完全是一个新的事务, 而 PROPAGATION_NESTED 则是外部事务的子事务, 如果外部事务 commit, 嵌套事务也会被 commit, 这个规则同样适用于 roll back
  • a072fa038320:写的很好 如果楼主能吧对应的github 源码的地址贴出来 就好了。。。。
    张丰哲:恩恩,欢迎继续关注,以后会改进的哈~:smile:
  • b943df2d909c:老铁,源码可以发一份不:smile:
    张丰哲:老铁,我整理下,放到百度云上共享出来吧,:smile:
  • 1b41feaa555c:大佬有没有多数据源切换的demo
  • camlboy:楼主的每个文章都这么吓人,吓得我好想每一篇都关注你一次😀
    张丰哲:关注只能一次,但是点赞可以多次,:smiley:
  • tery007:你好,请问BasicDataSource是哪个类的子类,我用了java.sql.DataSource和spring的DriverManagerDataSource,都获取不了连接。在线等哦
    张丰哲:不好意思,久等了,:smile:
    BasicDataSource是DBCP连接池中的一个类,是javax.sql.DataSource的一个实现。
  • hequis:多个数据源可以吗?
    张丰哲:在本文中,做了一个简单的数据源路由,:smile:
  • iHelin:注意到线程7和2使用的是同一个connection,这样也是合理的吗?
    张丰哲:@iHelin 或者你可以分享下,为什么换了DRUID就不重复了呢?
    iHelin:@张丰哲 确实,刚试了下,换了druid连接池就不会重复:stuck_out_tongue_winking_eye:
    张丰哲:火眼金睛,点赞!
    合理的,因为数据库连接池的缘故~
  • 我是石老板:就是不懂
    我是石老板:@张丰哲 哈哈哈哈哈
    张丰哲:不懂也理直气壮,姿态很好看~哈哈

本文标题:透彻理解Spring事务设计思想之手写实现

本文链接:https://www.haomeiwen.com/subject/csbklxtx.html