spring的聲明式事務管理使用spring aop實現的,由於spring致力於無侵入性,一般不需要理解aop的概念就可以進行聲明式事務管理,
spring的聲明式事務管理可以在任何環境下使用,只需要更新配置文件,就可以和jdbc、hibernate或其他的事務機制一起工作,並且這中管理機制可以應用到任何一個java類以及類的實例上,同樣spring也提供了聲明式的回滾規則。但是spring的聲明式事務處理不提供高端應用服務器提供的跨越遠程調用的事務上下文傳播。
spring聲明式事務管理最重要的概念是:spring的事務管理是通過aop實現的,其中的事務通知由目前基於XML或者註解的元數據驅動,代理對象與事務元數據結合產生了一個aop代理,它使用一個PlatformTransactionManager
的實現品配合TransactionInterceptor
在方法執行的前後過程中實施事務。
當spring框架的事務基礎架構默認拋出運行時、unchecked Exception時,事務纔會回滾,也就是說如果拋出一個RuntimeException或者其子類時候。從事務中拋出的checked exception不會進行回滾操作。我們可以在配置文件中給具體的方法加上rollback-for = NoProductInStockException。有時候就算你不想在異常拋出的時候回滾事務,就可以使用不會滾的規則,no-rollback-for = instrumentNotFoundException。當然除了聲明式的事務回滾規則之外我們還可以通過編程式的方式來指定事務的回滾,例如下面
public void resolvePosition() { try { } catch (NoProductInStockException ex) { TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); } }
雖然寫法簡單,但是不符合spring提倡的無***性,並且使你的代碼與spring框架的事務高度耦合。
現在讓我們考慮一下這樣的場景,假設你有許多服務對象,你想爲他們分別設置完全不同的事務語義。 在Spring中,你可以通過分別定義特定的 <aop:advisor/>
元素, 讓每個advisor採用不同的 'pointcut'
和 'advice-ref'
屬性,來達到目的。如下
<aop:config> <aop:pointcut id="defaultServiceOperation" expression="execution(* x.y.service.*Service.*(..))"/> <aop:pointcut id="noTxServiceOperation" expression="execution(* x.y.service.ddl.DefaultDdlManager.*(..))"/> <aop:advisor pointcut-ref="defaultServiceOperation" advice-ref="defaultTxAdvice"/> <aop:advisor pointcut-ref="noTxServiceOperation" advice-ref="noTxAdvice"/> </aop:config> <bean id="fooService" class="x.y.service.DefaultFooService"/> <bean id="anotherFooService" class="x.y.service.ddl.DefaultDdlManager"/> <tx:advice id="defaultTxAdvice"> <tx:attributes> <tx:method name="get*" read-only="true"/> <tx:method name="*"/> </tx:attributes> </tx:advice> <tx:advice id="noTxAdvice"> <tx:attributes> <tx:method name="*" propagation="NEVER"/> </tx:attributes> </tx:advice>
除了基於xml配置文件的形式進行聲明式事務配置外,我們還可以使用註解的方式進行聲明式的事務管理,直接在java源碼中聲明事務語義的做法讓事務和將受其影響的代碼距離更近,而且一般來說不會有不恰當的耦合風險,@Transaction註解可用於接口定義和接口方法、類定義和類的public方法上,然而並不是加了這個註解就×××啓了事務行爲,它僅僅是一種元數據。我們用的時候儘量把註解加在類上,而不要加載接口上,因爲註解是不能繼承的,這就意味者如果你使用基於類的代理時,實物的設置將不能被基於類的代理所識別,而且對象也不會背事務代理包裝。