對於每一個JAVA程序員,spring應該是再熟悉不過的框架了,它的功能有多強大我就不多說了,既然他有這么強大的功能,是如何實現的呢?這個就需要從他的原理去了解,而最直接了解原理的方式莫過於源碼。當然Spring源碼那么大,有時候會顯得無從下手,而且也是晦澀難懂。所以我們可以按照功能模塊地方式去解讀,第一階段我就先跟大家分享下面spring的事務,讀源碼前,我們先得了解下spring事務的相關原理:事務的傳播特性和隔離級別
spring的傳播特性: PROPAGATION_REQUIRED, PROPAGATION_SUPPORTS, PROPAGATION_MANDATORY, PROPAGATION_REQUIRES_NEW, PROPAGATION_NOT_SUPPORTED, PROPAGATION_NEVER, PROPAGATION_NESTED
我們來一一介紹下
class A{ methodA(){ //邏輯處理 b.methodB(); //邏輯處理 } } class B{ methodB(); }
1.PROPAGATION_REQUIRED:如果存在一個事務,則支持當前事務。如果沒有事務則開啟
解釋:當A.methodA()和B.methodB()都打上REQUIRED的事務標志,執行A.methodA()方法的時候,看到上下文沒有事務,會新建一個事務,當執行到b.methodB()的時候,發現上下文已經有事務了,則不會新建事務,用A.methodA()新建的那個事務。
如果b.methodB()執行成功,a.methodA()執行失敗,那么b.methodB()和a.methodA()都會回滾(用的都是a.methodA()的事務)
2.PROPAGATION_SUPPORTS:如果存在一個事務,支持當前事務。如果沒有事務,則非事務的執行
解釋:當B.methodB()打上PROPAGATION_SUPPORTS的事務標志,執行A.methodA()方法,當執行到b.methodB()的時候,會檢查上下文有沒有事務,如果A.methodA()有事務,則b.methodB()沿用該事務,反之b.methodB()就以非事物的方式執行
3.PROPAGATION_MANDATORY:如果已經存在一個事務,支持當前事務。如果沒有一個活動的事務,則拋出異常
解釋:當B.methodB()打上PROPAGATION_MANDATORY的事務標志,執行A.methodA()方法,當執行到b.methodB()的時候,會檢查上下文有沒有事務,如果A.methodA()有事務,則b.methodB()沿用該事務,如果沒有,則會拋出異常
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與事務