spring|事務底層原理分析

spring自己沒有事務,spring事務是在數據庫事務的基礎上進行封裝拓展,spring支持聲明式事務、編程式事務兩種,本文主要針對聲明式事務進行講解,本篇文章爲《圖靈學院》課程筆記java

咱們在使用事務的時候無非是如下幾步git

  • 獲取數據庫鏈接 Connection con = DriverManager.getConnection()
  • 開啓事務con.setAutoCommit(true/false);
  • 執行數據操做(crud)
  • 提交事務/回滾事務 con.commit() / con.rollback()
  • 關閉鏈接 conn.close()

其實spring是在框架中給我咱們作了開啓、提交/回滾的操做,使得業務代碼和事務操做解耦。那麼spring是如何實如今指定方法先後自動加上事務操做的呢;這就要扯到動態代理了spring

代理模式

  • 解決的問題:將次要業務、主要業務解耦。,次要業務:起到輔助做用,輔助主要業務順利實現,在項目中每每大量存在數據庫

具體例子以下:編程

接口markdown

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;
                    }
                });
    }
}
複製代碼

測試方法ide

public static void main(String[] args) {
        //目標對象
        UserDao target = new UserDaoImpl();
        //目標對象建立代理對像
        UserDao proxy = (UserDao) new ProxyFactory(target).getProxyObject();
        proxy.save();
    }
複製代碼

輸出結果oop

結合着代理模式,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 事務運行時狀態

原文地址

cbaj.gitee.io/blog/2020/0…

相關文章
相關標籤/搜索