第二十五章 Spring之曾经的老朋友——事务

47 篇文章 0 订阅

Spring源码阅读目录

第一部分——IOC篇

第一章 Spring之最熟悉的陌生人——IOC
第二章 Spring之假如让你来写IOC容器——加载资源篇
第三章 Spring之假如让你来写IOC容器——解析配置文件篇
第四章 Spring之假如让你来写IOC容器——XML配置文件篇
第五章 Spring之假如让你来写IOC容器——BeanFactory和FactoryBean
第六章 Spring之假如让你来写IOC容器——Scope和属性填充
第七章 Spring之假如让你来写IOC容器——属性填充特别篇:SpEL表达式
第八章 Spring之假如让你来写IOC容器——拓展篇
第九章 Spring之源码阅读——环境搭建篇
第十章 Spring之源码阅读——IOC篇

第二部分——AOP篇

第十一章 Spring之不太熟的熟人——AOP
第十二章 Spring之不得不了解的内容——概念篇
第十三章 Spring之假如让你来写AOP——AOP联盟篇
第十四章 Spring之假如让你来写AOP——雏形篇
第十五章 Spring之假如让你来写AOP——Joinpoint(连接点)篇
第十六章 Spring之假如让你来写AOP——Pointcut(切点)篇
第十七章 Spring之假如让你来写AOP——Advice(通知)上篇
第十八章 Spring之假如让你来写AOP——Advice(通知)下篇
第十九章 Spring之假如让你来写AOP——番外篇:Spring早期设计
第二十章 Spring之假如让你来写AOP——Aspect(切面)篇
第二十一章 Spring之假如让你来写AOP——Weaver(织入器)篇
第二十二章 Spring之假如让你来写AOP——Target Object(目标对象)篇
第二十三章 Spring之假如让你来写AOP——融入IOC容器篇
第二十四章 Spring之源码阅读——AOP篇

第三部分——事务篇

第二十五章 Spring之曾经的老朋友——事务
第二十六章 Spring之假如让你来写事务——初稿篇
第二十七章 Spring之假如让你来写事务——铁三角篇
第二十八章 Spring之假如让你来写事务——属性篇
第二十九章 Spring之假如让你来写事务——状态篇
第三十章 Spring之假如让你来写事务——管理篇
第三十一章 Spring之假如让你来写事务——融入IOC容器篇
第三十二章 Spring之源码阅读——事务篇

第四部分——MVC篇

第三十三章 Spring之梦开始的地方——MVC
第三十四章 Spring之假如让你来写MVC——草图篇
第三十五章 Spring之假如让你来写MVC——映射器篇
第三十六章 Spring之假如让你来写MVC——拦截器篇
第三十七章 Spring之假如让你来写MVC——控制器篇
第三十八章 Spring之假如让你来写MVC——适配器篇
第三十九章 Spring之假如让你来写MVC——番外篇:类型转换
第四十章 Spring之假如让你来写MVC——ModelAndView篇
第四十一章 Spring之假如让你来写MVC——番外篇:数据绑定
第四十二章 Spring之假如让你来写MVC——视图篇
第四十三章 Spring之假如让你来写MVC——上传文件篇
第四十四章 Spring之假如让你来写MVC——异常处理器篇
第四十五章 Spring之假如让你来写MVC——国际化篇
第四十六章 Spring之假如让你来写MVC——主题解析器篇
第四十七章 Spring之假如让你来写MVC——闪存管理器篇
第四十八章 Spring之假如让你来写MVC——请求映射视图篇
第四十九章 Spring之假如让你来写MVC——番外篇:属性操作
第五十章 Spring之假如让你来写MVC——融入IOC容器篇
第五十一章 Spring之源码阅读——MVC篇



前言

    对于Spring一直都是既熟悉又陌生,说对它熟悉吧,平时用用没啥问题,但面试的时候被问的一脸懵逼,就很尴尬,都不好意思在简历上写着熟悉Spring了
在这里插入图片描述

    所以决定花点时间研究研究Spring的源码。主要参考的书籍是:《Spring源码深度解析(第2版)》、《Spring揭秘》、《Spring技术内幕:深入解析Spring架构与设计原理(第2版)》


     在前边的章节中, A君 分别完成了 Spring 最重要的两部分内容:IOCAOP。虽然过程比较坎坷,但是前途还是光明滴。接下来,A君 准备继续前行,开启新的篇章——事务篇

尝试动手写IOC容器

    出场人物:A君(苦逼的开发)、老大(项目经理)

    背景:老大要求A君在一周内开发个简单的 IOC容器

    前情提要: A君老大 的鞭策下,终于磕磕绊绊的实现了一个简单的 AOP 功能 。。。

事务?好像有点印象

    在经过一连串的加班后,A君 并没有迎来愉快地摸鱼时光,本以为在完成 AOP 部分后,或多或少会休息一段时间;没想到 老大 又开始布置任务了,任务的内容很简单:实现 事务,用 老大 的话说:“ AOP 都实现了,事务 就是顺手的事!”

    好,好,好,这么玩是吧!A君 无奈,又得被迫进步,去研究一下 事务 具体是个什么玩意了

    说到 事务,要说完全没印象那是不可能的,除非 A君 连最基础的CRUD都没开发过。可是要说有多熟悉吧,除却背面试题时记住点零零散散的知识点:什么 事务传播行为、什么 事务隔离级别 之外,也说不出其他东西来,甚至这些都是死记硬背的,说不出个所以然来。A君事务 了解也就止步于此了,想起之前说 AOP 时候,侃侃而谈,张嘴闭嘴以 事务 为例,自己却对它了解有限,这不经让 A君 老脸一红

    还是和从前一样, A君 先抛弃概念性的东西,依旧先写了个简单的例子,看看为什么 事务 会成为 AOP 的经典例子。代码如下:

    @Test
    public void tx() throws Exception {
        Properties properties = new Properties();
        properties.setProperty("druid.driverClassName", "com.mysql.cj.jdbc.Driver");
        properties.setProperty("druid.url", "jdbc:mysql://localhost:3306/spring?useSSL=false&serverTimezone=UTC");
        properties.setProperty("druid.username", "root");
        properties.setProperty("druid.password", "root");

        DruidDataSource dataSource = new DruidDataSource();
        dataSource.configFromPropety(properties);

        String sql = "UPDATE user SET name = ?,age=?,sex=? WHERE id = ?";
        Connection connection = null;
        PreparedStatement preparedStatement = null;

        try {
            connection = dataSource.getConnection();
            //关闭自动提交
            connection.setAutoCommit(false);
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1, "ls");
            preparedStatement.setInt(2, new Random().nextInt(100));
            preparedStatement.setString(3, "nv");
            preparedStatement.setInt(4, 11);
            preparedStatement.executeUpdate();
            connection.commit();
        } catch (Exception e) {
            e.printStackTrace();
            connection.rollback();
        } finally {
            if (preparedStatement != null) {
                preparedStatement.close();
            }
            if (connection != null) {
                connection.close();
            }
        }
    }

看着这个简单的例子,A君 就有点明白了:首先是获取连接,关闭自动提交,这点公共的。其次正常提交,失败回滚,这部分也是公共的。这不天然与 AOP 契合吗?只要把公共代码提取出来,添加一个切面,那么开发人员就可以专注于业务逻辑的开发,也不会忘记提交或者回滚,一举多得呀!怪不得说到 AOP 必然说起 事务。到目前为止,A君 依旧只是对 事务 有个感性的认识。不得已,A君 又去了解下相关内容。看了半天,好像懂了,但是话到嘴边,又不知从何说起?思来想去,A君 决定从 事务 为什么要存在的意义开始说起

    要说 事务 为什么存在,那就不得不提到一个经典的例子——转账。假设 A君 在商店购买100元的华子,当然得使用电子支付,不然就没有这档子事了。当中至少包括两个操作:

  1. A君 账户减少100元
  2. 小卖部账户增加100元

以这个例子为参考,再来看下 事务 的四个基本特性(ACID):

  • 原子性 (Atomicity):这名字起的,感觉是参考了化学术语。哈哈,为什么这么叫就不就结了。原子性解释为不可拆分。代入上面的例子看下:如果 A君 账户没有减少,而小卖部账户却增加了,那 A君 岂不是白嫖成功了,银行成了大冤种。如果A君 账户减少,而小卖部账户却没有增加,恐怕 A君 走不出小卖部了,银行恐成最大赢家。所以这两步不能再拆分了,必须同时成功或者失败,这次交易才算完成

  • 一致性(Consistency):如果说原子性是强调状态,那么一致性就是强调数据了。无论转账是否成功失败,那么金额的总数应该是一样的,转账成功的话:A君 账户减少100,而小卖部账户增加100,不能说 A君 账户扣了200,或者小卖部账户只增加了50,这样不论是 A君 还是小卖部,都要骂娘了。转账失败的话:两边的账户都应该保持不变,A君 账户不能无缘无故减少,小卖部账户也不能增加

  • 隔离性 (Isolation):隔离性也好理解,如果 A君 付款时,A君媳妇 也在用同一张卡付款,那么此时, A君A君媳妇 两者的 事务 应该是相互独立的,不能相互影响,总不能 A君媳妇 花了1w买个包,结果却转给小卖部,那可真是天降横财。虽然隔离性本身并不难理解,但是一涉及到并发,就不好理解了。首先是并发情况下,会产生几个问题:

  1. 脏读(Dirty Read):事务 A 读取到了事务 B 还未提交的数据,这些数据可能在事务 B 提交之前就发生了回滚。换句话说,事务 A 在读取数据时,读取了另一事务尚未提交的“脏数据”

  2. 不可重复读(Non-repeatable Read):事务 A 在两次读取相同数据时,发现数据已经发生了变化。也就是说,在同一个事务 A 中,查询到的同一数据被事务 B 修改了,导致事务 A 在不同时间点获取的数据不一致

  3. 幻读(Phantom Read):事务 A 执行查询时,查询的结果集在事务执行过程中发生了变化。通常是其他事务插入、删除或修改了满足查询条件的数据,导致事务 A 在两次查询时看到的结果集不一致

注:其实上面几个问题很好理解,只是 A君 在看这些概念的时候陷入了一个误区,以为事务指的是:insert、update、delete 这些操作才算,所以怎么看怎么变扭。其实事务应该是指开启事务的那一刻,到事务提交或者回滚的时候,才是结束。意味着在这中间,可以做任何操作,从而引出了脏读、不可重复读、幻读这些问题

    有了问题,自然就得想办法解决了,解决的办法也是面试热点题目——隔离级别。常见的事务隔离级别有四种,按照“隔离性”从低到高排序:

  1. Read Uncommitted(读未提交):看这名字就知道,这个隔离级别连脏读都解决不了,它也是最低的隔离级别,上诉几个问题都存在

  2. Read Committed(读已提交):这个也是见名知意,只能读取已提交的数据,自然而然也能解决脏读问题。但是无法避免不可重复读、幻读问题。是大部分数据库采用的默认隔离级别

  3. Repeatable Read(可重复读):一如既往的好理解,这个隔离级别,可以解决不可重复读、脏读的问题,但是无法避免幻读

  4. Serializable(可串行化):这是最严格的隔离级别,所有事务操作必须依次执行,退化成单线程,自然是最安全的,同时也是性能最差的

在这里插入图片描述

隔离级别脏读不可重复读幻读
Read Uncommitted(读未提交)允许允许允许
Read Committed(读已提交)不允许允许允许
Repeatable Read(可重复读)不允许不允许允许
Serializable(可串行化)不允许不允许不允许
  • 持久性 (Durability):持久?嗯。持久。首先声明,A君 没有想歪,持久性自然指的是 事务 一旦提交,所做的更改将永久保存,即使系统崩溃也不会丢失数据。不过话说回来,这个难道不是关系型数据库的基本操作,这玩意确定不是拿来凑数的?

    关于 事务 概念性的东西,就说到这里吧,再多的,A君 也不会了。这玩意实在是太理论了,就算不了解,也不影响后面写代码。如果后面有机会的话,去硬刚下数据库的时候,再把它拿下,哼哼。。。


总结

    正所谓树欲静而风不止,欲知后事如何,请看下回分解(✪ω✪)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

穷儒公羊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值