spring源碼解析--事務篇(前篇)

  對於每個JAVA程序員,spring應該是再熟悉不過的框架了,它的功能有多強大我就很少說了,既然他有這麼強大的功能,是如何實現的呢?這個就須要從他的原理去了解,而最直接瞭解原理的方式莫過於源碼。固然Spring源碼那麼大,有時候會顯得無從下手,並且也是晦澀難懂。因此咱們能夠按照功能模塊地方式去解讀,第一階段我就先跟你們分享下面spring的事務,讀源碼前,咱們先得了解下spring事務的相關原理:事務的傳播特性和隔離級別程序員

  spring的傳播特性: PROPAGATION_REQUIRED, PROPAGATION_SUPPORTS, PROPAGATION_MANDATORY, PROPAGATION_REQUIRES_NEW, PROPAGATION_NOT_SUPPORTED, PROPAGATION_NEVER, PROPAGATION_NESTEDspring

  咱們來一一介紹下數據庫

    class A{
        methodA(){
            //邏輯處理
            b.methodB();
            //邏輯處理
        }
    }
    class B{
        methodB();
    }

  1.PROPAGATION_REQUIRED:若是存在一個事務,則支持當前事務。若是沒有事務則開啓app

  解釋:當A.methodA()和B.methodB()都打上REQUIRED的事務標誌,執行A.methodA()方法的時候,看到上下文沒有事務,會新建一個事務,當執行到b.methodB()的時候,發現上下文已經有事務了,則不會新建事務,用A.methodA()新建的那個事務。框架

  若是b.methodB()執行成功,a.methodA()執行失敗,那麼b.methodB()和a.methodA()都會回滾(用的都是a.methodA()的事務)ide

  2.PROPAGATION_SUPPORTS:若是存在一個事務,支持當前事務。若是沒有事務,則非事務的執行ui

  解釋:當B.methodB()打上PROPAGATION_SUPPORTS的事務標誌,執行A.methodA()方法,當執行到b.methodB()的時候,會檢查上下文有沒有事務,若是A.methodA()有事務,則b.methodB()沿用該事務,反之b.methodB()就以非事物的方式執行this

  3.PROPAGATION_MANDATORY:若是已經存在一個事務,支持當前事務。若是沒有一個活動的事務,則拋出異常spa

  解釋:當B.methodB()打上PROPAGATION_MANDATORY的事務標誌,執行A.methodA()方法,當執行到b.methodB()的時候,會檢查上下文有沒有事務,若是A.methodA()有事務,則b.methodB()沿用該事務,若是沒有,則會拋出異常debug

  4.PROPAGATION_REQUIRES_NEW:老是開啓一個新的事務。若是一個事務已經存在,則將這個存在的事務掛起

  解釋:當B.methodB()打上PROPAGATION_REQUIRES_NEW的事務標誌,執行A.methodA()方法,當執行到b.methodB()的時候,會檢查上下文有沒有事務,若是A.methodA()有事務,則會掛起A.methodA()的事務,新建一個屬於b.methodB(),當b.methodB()

  的事務執行結束的時候,則會喚醒b.methodB()的事務。和PROPAGATION_REQUIRED的差異在於回滾,當b.methodB()的事務提交後,A.methodA()執行失敗,只會回滾A.methodA不會回滾b.methodB(),當b.methodB()執行失敗,異常被A.methodA()方法   

   catch到的話,A.methodA()事務不會回滾

  5.PROPAGATION_NOT_SUPPORTED:老是非事務地執行,並掛起任何存在的事務

  解釋:當B.methodB()打上PROPAGATION_NOT_SUPPORTED的事務標誌,執行A.methodA()方法,當執行到b.methodB()的時候,會檢查上下文有沒有事務,若是A.methodA()有事務,則會掛起A.methodA()的事務,當執行完b.methodB()方法的時候,             A.methodA()方法繼續以事務的方式執行

  6.PROPAGATION_NEVER: 老是非事務地執行,若是存在一個活動事務,則拋出異常

  解釋:當B.methodB()打上PROPAGATION_NEVER的事務標誌,執行A.methodA()方法,當執行到b.methodB()的時候,會檢查上下文有沒有事務,若是有事務,則拋出異常,若是沒有則以非事務執行

  7.PROPAGATION_NESTED:若是一個活動的事務存在,則運行在一個嵌套的事務中. 若是沒有活動事務, PROPAGATION_REQUIRED 屬性執行

  解釋:當B.methodB()打上PROPAGATION_NOT_SUPPORTED的事務標誌,執行A.methodA()方法,當執行到b.methodB()的時候,若是A.methodA()方法有事務,則會用當前事務,若是 b.methodB()執行失敗,只會回滾  b.methodB(),不會回滾A.methodA(),   只有當A.methodA()執行完成後纔會提交b.methodB()的事務,若是A.methodA()方法沒有事務,就會新建一個事務;

  事務隔離級別:  ISOLATION_DEFAULT,ISOLATION_READ_UNCOMMITTED,ISOLATION_READ_COMMITTED,ISOLATION_REPEATABLE_READ,ISOLATION_SERIALIZABLE 

  1.ISOLATION_DEFAULT:這是一個PlatfromTransactionManager默認的隔離級別,使用數據庫默認的事務隔離級別   

  2. ISOLATION_READ_UNCOMMITTED 這是事務最低的隔離級別,它充許別外一個事務能夠看到這個事務未提交的數據。這種隔離級別會產生髒讀,不可重複讀和幻像讀。 

  3. ISOLATION_READ_COMMITTED  :保證一個事務修改的數據提交後才能被另一個事務讀取。另一個事務不能讀取該事務未提交的數據。這種事務隔離級別能夠避免髒讀出現,可是可能會出現不可重複讀和幻像讀。:

  4. ISOLATION_REPEATABLE_READ  :這種事務隔離級別能夠防止髒讀,不可重複讀。可是可能出現幻像讀。 

  5. ISOLATION_SERIALIZABLE :這是花費最高代價可是最可靠的事務隔離級別。事務被處理爲順序執行。除了防止髒讀,不可重複讀外,還避免了幻讀。

  ok,如今咱們事務的傳播特性和隔離級別有了必定的瞭解。咱們開始去嘗試閱讀源碼

  想要閱讀源碼,咱們必須先弄清楚spring事務的幾個類和接口的關係,先看下圖:

  

  事務的定義接口:TransactionDefinition 

  包含事務的兩個重要屬性:傳播特性和隔離級別(上面已做介紹,不在重複)

public interface TransactionDefinition {
    int PROPAGATION_REQUIRED = 0;
    int PROPAGATION_SUPPORTS = 1;
    int PROPAGATION_MANDATORY = 2;
    int PROPAGATION_REQUIRES_NEW = 3;
    int PROPAGATION_NOT_SUPPORTED = 4;
    int PROPAGATION_NEVER = 5;
    int PROPAGATION_NESTED = 6;
    int ISOLATION_DEFAULT = -1;
    int ISOLATION_READ_UNCOMMITTED = 1;
    int ISOLATION_READ_COMMITTED = 2;
    int ISOLATION_REPEATABLE_READ = 4;
    int ISOLATION_SERIALIZABLE = 8;
    int TIMEOUT_DEFAULT = -1;

    int getPropagationBehavior();

    int getIsolationLevel();

    int getTimeout();

    boolean isReadOnly();

    String getName();
}

   TransactionDefinition 的一個實現類:DefaultTransactionDefinition

  就是對上述屬性設置一些默認值,默認的傳播特性爲PROPAGATION_REQUIRED ,隔離級別爲ISOLATION_DEFAULT 

public class DefaultTransactionDefinition implements TransactionDefinition, Serializable {
    public static final String PREFIX_PROPAGATION = "PROPAGATION_";
    public static final String PREFIX_ISOLATION = "ISOLATION_";
    public static final String PREFIX_TIMEOUT = "timeout_";
    public static final String READ_ONLY_MARKER = "readOnly";
    static final Constants constants = new Constants(TransactionDefinition.class);
    private int propagationBehavior = 0;//默認值 private int isolationLevel = -1; private int timeout = -1; private boolean readOnly = false;  private String name;

    public DefaultTransactionDefinition() {
    }

    public DefaultTransactionDefinition(TransactionDefinition other) {
        this.propagationBehavior = other.getPropagationBehavior();
        this.isolationLevel = other.getIsolationLevel();
        this.timeout = other.getTimeout();
        this.readOnly = other.isReadOnly();
        this.name = other.getName();
    }

    public DefaultTransactionDefinition(int propagationBehavior) {
        this.propagationBehavior = propagationBehavior;
    }

    public final void setPropagationBehaviorName(String constantName) throws IllegalArgumentException {
        if(constantName != null && constantName.startsWith("PROPAGATION_")) {
            this.setPropagationBehavior(constants.asNumber(constantName).intValue());
        } else {
            throw new IllegalArgumentException("Only propagation constants allowed");
        }
    }

    public final void setPropagationBehavior(int propagationBehavior) {
        if(!constants.getValues("PROPAGATION_").contains(Integer.valueOf(propagationBehavior))) {
            throw new IllegalArgumentException("Only values of propagation constants allowed");
        } else {
            this.propagationBehavior = propagationBehavior;
        }
    }

    public final int getPropagationBehavior() {
        return this.propagationBehavior;
    }

    public final void setIsolationLevelName(String constantName) throws IllegalArgumentException {
        if(constantName != null && constantName.startsWith("ISOLATION_")) {
            this.setIsolationLevel(constants.asNumber(constantName).intValue());
        } else {
            throw new IllegalArgumentException("Only isolation constants allowed");
        }
    }

    public final void setIsolationLevel(int isolationLevel) {
        if(!constants.getValues("ISOLATION_").contains(Integer.valueOf(isolationLevel))) {
            throw new IllegalArgumentException("Only values of isolation constants allowed");
        } else {
            this.isolationLevel = isolationLevel;
        }
    }

    public final int getIsolationLevel() {
        return this.isolationLevel;
    }

    public final void setTimeout(int timeout) {
        if(timeout < -1) {
            throw new IllegalArgumentException("Timeout must be a positive integer or TIMEOUT_DEFAULT");
        } else {
            this.timeout = timeout;
        }
    }

    public final int getTimeout() {
        return this.timeout;
    }

    public final void setReadOnly(boolean readOnly) {
        this.readOnly = readOnly;
    }

    public final boolean isReadOnly() {
        return this.readOnly;
    }

    public final void setName(String name) {
        this.name = name;
    }

    public final String getName() {
        return this.name;
    }

    public boolean equals(Object other) {
        return other instanceof TransactionDefinition && this.toString().equals(other.toString());
    }

    public int hashCode() {
        return this.toString().hashCode();
    }

    public String toString() {
        return this.getDefinitionDescription().toString();
    }

    protected final StringBuilder getDefinitionDescription() {
        StringBuilder result = new StringBuilder();
        result.append(constants.toCode(Integer.valueOf(this.propagationBehavior), "PROPAGATION_"));
        result.append(',');
        result.append(constants.toCode(Integer.valueOf(this.isolationLevel), "ISOLATION_"));
        if(this.timeout != -1) {
            result.append(',');
            result.append("timeout_").append(this.timeout);
        }

        if(this.readOnly) {
            result.append(',');
            result.append("readOnly");
        }

        return result;
    }
}

    TransactionAttribute接口

 定義對什麼類型的異常進行回滾

public interface TransactionAttribute extends TransactionDefinition {
    String getQualifier();

    boolean rollbackOn(Throwable var1);
}

  TransactionAttribute的實現類:DefaultTransactionAttribute

 指明瞭默認對RuntimeException 和Error都進行回滾

public class DefaultTransactionAttribute extends DefaultTransactionDefinition implements TransactionAttribute {
    private String qualifier;

    public DefaultTransactionAttribute() {
    }

    public DefaultTransactionAttribute(TransactionAttribute other) {
        super(other);
    }

    public DefaultTransactionAttribute(int propagationBehavior) {
        super(propagationBehavior);
    }

    public void setQualifier(String qualifier) {
        this.qualifier = qualifier;
    }

    public String getQualifier() {
        return this.qualifier;
    }

    public boolean rollbackOn(Throwable ex) {//指明瞭對RuntimeException 和Error進行回滾 return ex instanceof RuntimeException || ex instanceof Error;
    }

    protected final StringBuilder getAttributeDescription() {
        StringBuilder result = this.getDefinitionDescription();
        if(this.qualifier != null) {
            result.append("; '").append(this.qualifier).append("'");
        }

        return result;
    }
}

   事務模板類TransactionTemplate

   他的核心是裏面有PlatformTransactionManager 這個事務管理類,用它來對事務提交和回滾。咱們的業務邏輯只要寫在TransactionCallback.doInTransaction()方法裏面既能夠,每次執行這個方法前,先會transactionManager.getTransaction(this)開啓一   個事務,執行TransactionCallback.doInTransaction()異常的話會調用transactionManager.rollback(status)來回滾事務,正確的話就會調用transactionManager.commit(status)提交事務;

public class TransactionTemplate extends DefaultTransactionDefinition implements TransactionOperations, InitializingBean {
    protected final Log logger = LogFactory.getLog(this.getClass());
    private PlatformTransactionManager transactionManager;

    public TransactionTemplate() {
    }

    public TransactionTemplate(PlatformTransactionManager transactionManager) {
        this.transactionManager = transactionManager;
    }

    public TransactionTemplate(PlatformTransactionManager transactionManager, TransactionDefinition transactionDefinition) {
        super(transactionDefinition);
        this.transactionManager = transactionManager;
    }

    public void setTransactionManager(PlatformTransactionManager transactionManager) {
        this.transactionManager = transactionManager;
    }

    public PlatformTransactionManager getTransactionManager() {
        return this.transactionManager;
    }

    public void afterPropertiesSet() {
        if(this.transactionManager == null) {
            throw new IllegalArgumentException("Property 'transactionManager' is required");
        }
    }

    public <T> T execute(TransactionCallback<T> action) throws TransactionException {
        if(this.transactionManager instanceof CallbackPreferringPlatformTransactionManager) {
            return ((CallbackPreferringPlatformTransactionManager)this.transactionManager).execute(this, action);
        } else {
            TransactionStatus status = this.transactionManager.getTransaction(this);

            Object result;
            try {
                result = action.doInTransaction(status);//業務邏輯代碼寫在這裏
            } catch (RuntimeException var5) {
                this.rollbackOnException(status, var5);
                throw var5;
            } catch (Error var6) {
                this.rollbackOnException(status, var6);
                throw var6;
            } catch (Exception var7) {
                this.rollbackOnException(status, var7);
                throw new UndeclaredThrowableException(var7, "TransactionCallback threw undeclared checked exception");
            }

            this.transactionManager.commit(status);
            return result;
        }
    }

    private void rollbackOnException(TransactionStatus status, Throwable ex) throws TransactionException {
        this.logger.debug("Initiating transaction rollback on application exception", ex);

        try {
            this.transactionManager.rollback(status);
        } catch (TransactionSystemException var4) {
            this.logger.error("Application exception overridden by rollback exception", ex);
            var4.initApplicationException(ex);
            throw var4;
        } catch (RuntimeException var5) {
            this.logger.error("Application exception overridden by rollback exception", ex);
            throw var5;
        } catch (Error var6) {
            this.logger.error("Application exception overridden by rollback error", ex);
            throw var6;
        }
    }
}

基於上面的模板類,咱們能夠這樣來實現數據庫的事務,把每一個邏輯都寫在TransactionCallback.doInTransaction()方法裏面,他會自動幫咱們提交事務

TransactionTemplate transactionTemplate=new TransactionTemplate();
transactionTemplate.setTransactionManager(platformTransactionManager);
        
        transactionTemplate.execute(new TransactionCallback<String>() {

            @Override
            public String doInTransaction(TransactionStatus status) {
                //數據庫操做
                return "success";
            }
        });

可是這樣會使每一個數據庫方法都要要寫到TransactionCallback.doInTransaction(),其實耦合度仍是很高。Spring因而推出了他的AOP管理事務

這個我會在下一篇詳細介紹spring-aop與事務

相關文章
相關標籤/搜索