美文网首页
几个直击灵魂的Spring拷问(四)

几个直击灵魂的Spring拷问(四)

作者: 千淘萬漉 | 来源:发表于2020-09-28 09:29 被阅读0次

这一篇来重点讲讲Spring中的事务。

1、Spring和事务的关系:

  • 事务性资源:如关系型数据库Mysql、Oracle、某些消息队列中间件等,因为它们本身支持事务,也能够处理事务。
  • Spring不是事务性资源,但是它可以管理事务性资源,所以Spring和事务之间是管理关系。

2、Spring事务三要素:

  • 数据源:表示具体的事务性资源,是事务的真正处理者,如MySQL等。
  • 事务管理器:像一个大管家,从整体上管理事务的处理过程,如打开、提交、回滚等。
  • 事务应用和属性配置:像一个标识符,表明哪些方法要参与事务,如何参与事务,以及一些相关属性如隔离级别、超时时间等。

3、事务的基本原理:

Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供事务功能的。对于纯JDBC操作数据库,想要用到事务,可以按照以下步骤进行:

  • 获取连接 Connection con = DriverManager.getConnection()
  • 开启事务con.setAutoCommit(true/false);
  • 执行CRUD
  • 提交事务/回滚事务 con.commit() / con.rollback();
  • 关闭连接 conn.close();

使用Spring的事务管理功能后,我们可以不再写步骤 2 和 4 的代码,而是由Spirng 自动完成。那么Spring是如何在我们书写的 CRUD 之前和之后开启事务和关闭事务的呢?解决这个问题,也就可以从整体上理解Spring的事务管理实现原理了。

以注解方式为例子:
1、配置文件开启注解驱动,在相关的类和方法上通过注解@Transactional标识。
2、spring 在启动的时候会去解析生成相关的bean,这时候会查看拥有相关注解的类和方法,并且为这些类和方法生成代理,并根据@Transaction的相关参数进行相关配置注入,这样就在代理中为我们把相关的事务处理掉了(开启正常提交事务,异常回滚事务)。
3、真正的数据库层的事务提交和回滚是通过binlog或者redo log实现的。

4.事务类型

分为两种:编程式事务、声明式事务

(1)编程式事务

编程式事务管理使用TransactionTemplate或者直接使用底层的PlatformTransactionManager。对于编程式事务管理,spring推荐使用TransactionTemplate。很少用,但是可以看下官网的例子:

public class SimpleService implements Service {

    private final TransactionTemplate transactionTemplate;
    
    // 使用构造对transactionTemplate进行初始化
    // 需要提供一个transactionManager
    public SimpleService(PlatformTransactionManager transactionManager) {
        this.transactionTemplate = new  TransactionTemplate(transactionManager);
    }

    public Object someServiceMethod() {
        return transactionTemplate.execute(new TransactionCallback() {
            public Object doInTransaction(TransactionStatus status) {
                // 这里实现自己的相关业务逻辑
                updateOperation1();
                return resultOfUpdateOperation2();
            }
        });
    }
}

在上面的例子中,显示的使用了 TransactionTemplate 来完成事务管理,通过实现 TransactionCallback 接口并在其 doInTransaction 方法中完成了我们对业务的处理。我们可以大概看下 TransactionTemplate的execute 方法的实现,实际上就是通过一个 TransactionCallback 封装了业务逻辑,然后 TransactionTemplate 会在事务的上下文中调用:

public <T> T execute(TransactionCallback<T> action) throws TransactionException {
        Assert.state(this.transactionManager != null, "No PlatformTransactionManager set");

        if (this.transactionManager instanceof CallbackPreferringPlatformTransactionManager) {
            return ((CallbackPreferringPlatformTransactionManager) this.transactionManager).execute(this, action);
        }
        else {
            // 1.通过事务管理器开启事务
            TransactionStatus status = this.transactionManager.getTransaction(this);
            T result;
            try {
                // 2.执行传入的业务逻辑
                result = action.doInTransaction(status);
            }
            catch (RuntimeException | Error ex) {
                // 3.出现异常,进行回滚
                rollbackOnException(status, ex);
                throw ex;
            }
            catch (Throwable ex) {
                // 3.出现异常,进行回滚
                rollbackOnException(status, ex);
                throw new UndeclaredThrowableException(ex, 
                     "TransactionCallback threw undeclared checked exception");
            }
            // 4.正常执行完成的话,提交事务
            this.transactionManager.commit(status);
            return result;
        }
    }

(2)声明式事务

声明式事务管理建立在AOP之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过基于@Transactional注解的方式),便可以将事务规则应用到业务逻辑中。

显然声明式事务管理要优于编程式事务管理,这正是spring倡导的非侵入式的开发方式。声明式事务管理也有两种常用的方式,一种是基于xml配置文件,另一种就是基于@Transactional注解。显然基于注解的方式更简单易用,更清爽。

Spring事务配置

spring Boot 使用事务非常简单,首先使用注解 @EnableTransactionManagement 开启事务支持后,然后在访问数据库的Service方法上添加注解 @Transactional 便可。

相关文章

网友评论

      本文标题:几个直击灵魂的Spring拷问(四)

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