建议收藏!spring事务底层原理分析

spring本身没有事务,spring事务是在数据库事务的基础上进行封装拓展,spring支持声明式事务、编程式事务两种,本文主要针对声明式事务进行讲解。

我们在使用事务的时候无非是以下几步

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

其实spring是在框架中给我我们做了开启、提交/回滚的操作,使得业务代码和事务操作解耦。那么spring是如何实现在指定方法前后自动加上事务操作的呢;这就要扯到动态代理了

代理模式

  • 解决的问题:将次要业务、主要业务解耦。,次要业务:起到辅助作用,辅助主要业务顺利实现,在项目中往往大量存在

具体例子如下:

接口

public interface UserDao {
     void save();
}

接口实现、目标对象

public class UserDaoImpl implements UserDao {
    @Override
    public void save() {
        System.out.println("数据已经保存");
    }
}

代理对象

public class ProxyFactory {

    private  Object target;

    public ProxyFactory(Object object) {
        this.target = object;
    }

    public Object getProxyObject(){
       return  Proxy.newProxyInstance(target.getClass().getClassLoader(),
                 target.getClass().getInterfaces(),new InvocationHandler(){
                   /**
                    * @param proxy 负责监听的对象
                    * @param method 被拦截的业务方法
                    * @param args 被拦截业务方法的实参
                    * @return
                    * @throws Throwable
                    */
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("before do something...");
                         Object returnValue= method.invoke(target,args);
                        System.out.println("after do something...");
                        return returnValue;
                    }
                });
    }
}

测试方法

public static void main(String[] args) {
     //目标对象
     UserDao target = new UserDaoImpl();
     //目标对象创建代理对像
     UserDao proxy = (UserDao) new ProxyFactory(target).getProxyObject();
     proxy.save();
 }

输出结果

结合着代理模式,spring事务的实现原理就容易理解了,业务逻辑就是主要业务,需要重复使用的事务就是次要业务,spring的事务就是通过动态代理在业务代码的前后增加开启、提交/回滚的操作,实现事务操作

spring事务特性如下

  • 支持原有数据事务的隔离级别
  • 加入事务传播特性概念,提供多个事务的合并或隔离的功能
  • 提供声明式事务,让业务代码和事务分离,事务简单易用

spring事务的传播特性

属性属性值描述
支持当前事物PROPAGATION_REQUIRED(必须的)如果当前没有事物,就新建一个事物,如果已经存在一个事物中,加入到这个事物中。这是最常见的选择。
PROPAGATION_SUPPORTS(支持)支持当前事物,如果当前没有事物,就以非事物方式执行。
PROPAGATION_MANDATORY(强制)使用当前的事物,如果当前没有事物,就抛出异常。
不支持当前事物PROPAGATION_REQUIRES_NEW(隔离)新建事物,如果当前存在事物,把当前事物挂起。
PROPAGATION_NOT_SUPPORTED(不支持)以非事物方式执行操作,如果当前存在事物,就把当前事物挂起。
PROPAGATION_NEVER(强制非事物)以非事物方式执行,如果当前存在事物,则抛出异常。
套事物PROPAGATION_NESTED(嵌套事物)如果当前存在事物,则在嵌套事物内执行。如果当前没有事物,则执行与PROPAGATION_REQUIRED类似的操作。

spring事务隔离级别

隔离级别脏读(Dirty Read)不可重复读(NonRepeatable Read)幻读(Phantom Read)
未提交读(Read uncommitted)可能可能可能
已提交读(Read committed)不可能可能可能
可重复读(Repeatable read)不可能不可能可能
可串行化(SERIALIZABLE)不可能不可能不可能

脏读 :

一个事物读取到另一事物未提交的更新数据

不可重复读 :

在同一事物中,多次读取同一数据返回的结果有所不同, 换句话说, 后续读取可以读到另一事物已提交的更新数据. 相反, “可重复读”在同一事物中多次读取数据时, 能够保证所读数据一样, 也就是后续读取不能读到另一事物已提交的更新数据。

幻读 :

查询表中一条数据如果不存在就插入一条,并发的时候却发现,里面居然有两条相同的数据。这就幻读的问题。

spring提供三个接口提供使用事务:

  • TransactionDefinition 事务定义

  • PlatformTransactionManager 事务管理

  • TransactionStatus 事务运行时状态

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值